mirror of
https://github.com/youwen5/iamb.git
synced 2025-06-20 05:39:52 -07:00
Add command to set per-room notification levels (#305)
This commit is contained in:
parent
b4fc574163
commit
2a66496913
4 changed files with 135 additions and 1 deletions
19
docs/iamb.1
19
docs/iamb.1
|
@ -122,6 +122,25 @@ View a list of members of the currently focused room.
|
|||
Set the name of the currently focused room.
|
||||
.It Sy ":room name unset"
|
||||
Unset the name of the currently focused room.
|
||||
.It Sy ":room notify set [level]"
|
||||
Set a notification level for the currently focused room.
|
||||
Valid levels are
|
||||
.Dq mute ,
|
||||
.Dq mentions ,
|
||||
.Dq keywords ,
|
||||
and
|
||||
.Dq all .
|
||||
Note that
|
||||
.Dq mentions
|
||||
and
|
||||
.Dq keywords
|
||||
are aliases for the same behaviour.
|
||||
.It Sy ":room notify unset"
|
||||
Unset any room-level notification configuration.
|
||||
.It Sy ":room notify show"
|
||||
Show the current room-level notification configuration.
|
||||
If the room is using the account-level default, then this will print
|
||||
.Dq default .
|
||||
.It Sy ":room tag set [tag]"
|
||||
Add a tag to the currently focused room.
|
||||
.It Sy ":room tag unset [tag]"
|
||||
|
|
10
src/base.rs
10
src/base.rs
|
@ -378,6 +378,9 @@ pub enum RoomField {
|
|||
/// The room topic.
|
||||
Topic,
|
||||
|
||||
/// Notification level.
|
||||
NotificationMode,
|
||||
|
||||
/// The room's entire list of alternative aliases.
|
||||
Aliases,
|
||||
|
||||
|
@ -612,6 +615,10 @@ pub type MessageReactions = HashMap<OwnedEventId, (String, OwnedUserId)>;
|
|||
/// Errors encountered during application use.
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum IambError {
|
||||
/// An invalid notification level was specified.
|
||||
#[error("Invalid notification level: {0}")]
|
||||
InvalidNotificationLevel(String),
|
||||
|
||||
/// An invalid user identifier was specified.
|
||||
#[error("Invalid user identifier: {0}")]
|
||||
InvalidUserId(String),
|
||||
|
@ -691,6 +698,9 @@ pub enum IambError {
|
|||
#[error("Verification request error: {0}")]
|
||||
VerificationRequestError(#[from] matrix_sdk::encryption::identities::RequestVerificationError),
|
||||
|
||||
#[error("Notification setting error: {0}")]
|
||||
NotificationSettingError(#[from] matrix_sdk::NotificationSettingsError),
|
||||
|
||||
/// A failure related to images.
|
||||
#[error("Image error: {0}")]
|
||||
Image(#[from] image::ImageError),
|
||||
|
|
|
@ -34,7 +34,7 @@ type ProgResult = CommandResult<ProgramCommand>;
|
|||
|
||||
/// Convert strings the user types into a tag name.
|
||||
fn tag_name(name: String) -> Result<TagName, CommandError> {
|
||||
let tag = match name.as_str() {
|
||||
let tag = match name.to_lowercase().as_str() {
|
||||
"fav" | "favorite" | "favourite" | "m.favourite" => TagName::Favorite,
|
||||
"low" | "lowpriority" | "low_priority" | "low-priority" | "m.lowpriority" => {
|
||||
TagName::LowPriority
|
||||
|
@ -431,6 +431,18 @@ fn iamb_room(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
|
|||
("tag", "set", Some(s)) => RoomAction::Set(RoomField::Tag(tag_name(s)?), "".into()).into(),
|
||||
("tag", "set", None) => return Result::Err(CommandError::InvalidArgument),
|
||||
|
||||
// :room notify set <notification-level>
|
||||
("notify", "set", Some(s)) => RoomAction::Set(RoomField::NotificationMode, s).into(),
|
||||
("notify", "set", None) => return Result::Err(CommandError::InvalidArgument),
|
||||
|
||||
// :room notify unset <notification-level>
|
||||
("notify", "unset", None) => RoomAction::Unset(RoomField::NotificationMode).into(),
|
||||
("notify", "unset", Some(_)) => return Result::Err(CommandError::InvalidArgument),
|
||||
|
||||
// :room notify show
|
||||
("notify", "show", None) => RoomAction::Show(RoomField::NotificationMode).into(),
|
||||
("notify", "show", Some(_)) => return Result::Err(CommandError::InvalidArgument),
|
||||
|
||||
// :room tag unset <tag-name>
|
||||
("tag", "unset", Some(s)) => RoomAction::Unset(RoomField::Tag(tag_name(s)?)).into(),
|
||||
("tag", "unset", None) => return Result::Err(CommandError::InvalidArgument),
|
||||
|
@ -977,6 +989,27 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cmd_room_notification_mode_set() {
|
||||
let mut cmds = setup_commands();
|
||||
let ctx = EditContext::default();
|
||||
|
||||
let cmd = format!("room notify set mute");
|
||||
let res = cmds.input_cmd(&cmd, ctx.clone()).unwrap();
|
||||
let act = RoomAction::Set(RoomField::NotificationMode, "mute".into());
|
||||
assert_eq!(res, vec![(act.into(), ctx.clone())]);
|
||||
|
||||
let cmd = format!("room notify unset");
|
||||
let res = cmds.input_cmd(&cmd, ctx.clone()).unwrap();
|
||||
let act = RoomAction::Unset(RoomField::NotificationMode);
|
||||
assert_eq!(res, vec![(act.into(), ctx.clone())]);
|
||||
|
||||
let cmd = format!("room notify show");
|
||||
let res = cmds.input_cmd(&cmd, ctx.clone()).unwrap();
|
||||
let act = RoomAction::Show(RoomField::NotificationMode);
|
||||
assert_eq!(res, vec![(act.into(), ctx.clone())]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cmd_invite() {
|
||||
let mut cmds = setup_commands();
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
use std::collections::HashSet;
|
||||
|
||||
use matrix_sdk::{
|
||||
notification_settings::RoomNotificationMode,
|
||||
room::Room as MatrixRoom,
|
||||
ruma::{
|
||||
api::client::{
|
||||
|
@ -82,6 +83,19 @@ macro_rules! delegate {
|
|||
};
|
||||
}
|
||||
|
||||
fn notification_mode(name: impl Into<String>) -> IambResult<RoomNotificationMode> {
|
||||
let name = name.into();
|
||||
|
||||
let mode = match name.to_lowercase().as_str() {
|
||||
"mute" => RoomNotificationMode::Mute,
|
||||
"mentions" | "keywords" => RoomNotificationMode::MentionsAndKeywordsOnly,
|
||||
"all" => RoomNotificationMode::AllMessages,
|
||||
_ => return Err(IambError::InvalidNotificationLevel(name).into()),
|
||||
};
|
||||
|
||||
Ok(mode)
|
||||
}
|
||||
|
||||
/// State for a Matrix room or space.
|
||||
///
|
||||
/// Since spaces function as special rooms within Matrix, we wrap their window state together, so
|
||||
|
@ -296,6 +310,16 @@ impl RoomState {
|
|||
let ev = RoomTopicEventContent::new(value);
|
||||
let _ = room.send_state_event(ev).await.map_err(IambError::from)?;
|
||||
},
|
||||
RoomField::NotificationMode => {
|
||||
let mode = notification_mode(value)?;
|
||||
let client = &store.application.worker.client;
|
||||
let notifications = client.notification_settings().await;
|
||||
|
||||
notifications
|
||||
.set_room_notification_mode(self.id(), mode)
|
||||
.await
|
||||
.map_err(IambError::from)?;
|
||||
},
|
||||
RoomField::CanonicalAlias => {
|
||||
let client = &mut store.application.worker.client;
|
||||
|
||||
|
@ -399,6 +423,15 @@ impl RoomState {
|
|||
let ev = RoomTopicEventContent::new("".into());
|
||||
let _ = room.send_state_event(ev).await.map_err(IambError::from)?;
|
||||
},
|
||||
RoomField::NotificationMode => {
|
||||
let client = &store.application.worker.client;
|
||||
let notifications = client.notification_settings().await;
|
||||
|
||||
notifications
|
||||
.delete_user_defined_room_rules(self.id())
|
||||
.await
|
||||
.map_err(IambError::from)?;
|
||||
},
|
||||
RoomField::CanonicalAlias => {
|
||||
let Some(alias_to_destroy) = room.canonical_alias() else {
|
||||
let msg = "This room has no canonical alias to unset";
|
||||
|
@ -481,6 +514,21 @@ impl RoomState {
|
|||
Some(topic) => format!("Room topic: {topic:?}"),
|
||||
}
|
||||
},
|
||||
RoomField::NotificationMode => {
|
||||
let client = &store.application.worker.client;
|
||||
let notifications = client.notification_settings().await;
|
||||
let mode =
|
||||
notifications.get_user_defined_room_notification_mode(self.id()).await;
|
||||
|
||||
let level = match mode {
|
||||
Some(RoomNotificationMode::Mute) => "mute",
|
||||
Some(RoomNotificationMode::MentionsAndKeywordsOnly) => "keywords",
|
||||
Some(RoomNotificationMode::AllMessages) => "all",
|
||||
None => "default",
|
||||
};
|
||||
|
||||
format!("Room notification level: {level:?}")
|
||||
},
|
||||
RoomField::Aliases => {
|
||||
let aliases = room
|
||||
.alt_aliases()
|
||||
|
@ -677,3 +725,27 @@ impl WindowOps<IambInfo> for RoomState {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_parse_room_notification_level() {
|
||||
let tests = vec![
|
||||
("mute", RoomNotificationMode::Mute),
|
||||
("mentions", RoomNotificationMode::MentionsAndKeywordsOnly),
|
||||
("keywords", RoomNotificationMode::MentionsAndKeywordsOnly),
|
||||
("all", RoomNotificationMode::AllMessages),
|
||||
];
|
||||
|
||||
for (input, expect) in tests {
|
||||
let res = notification_mode(input).unwrap();
|
||||
assert_eq!(expect, res);
|
||||
}
|
||||
|
||||
assert!(notification_mode("invalid").is_err());
|
||||
assert!(notification_mode("not a level").is_err());
|
||||
assert!(notification_mode("@user:example.com").is_err());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue