generated from t/malachite
add: ability to mute chats
This commit is contained in:
parent
ff1c739367
commit
01fa758e63
11 changed files with 121 additions and 7 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -2998,7 +2998,7 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
|
|||
|
||||
[[package]]
|
||||
name = "tawny"
|
||||
version = "1.0.4"
|
||||
version = "1.0.5"
|
||||
dependencies = [
|
||||
"ammonia",
|
||||
"axum",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "tawny"
|
||||
version = "1.0.4"
|
||||
version = "1.0.5"
|
||||
edition = "2024"
|
||||
authors = ["trisuaso"]
|
||||
repository = "https://trisua.com/t/tawny"
|
||||
|
|
|
@ -441,3 +441,23 @@ function clear_notifications() {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
function mute_chat() {
|
||||
fetch(`/api/v1/chats/${STATE.chat_id}/mute`, {
|
||||
method: "POST",
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then((res) => {
|
||||
show_message(res.message, res.ok);
|
||||
});
|
||||
}
|
||||
|
||||
function unmute_chat() {
|
||||
fetch(`/api/v1/chats/${STATE.chat_id}/mute`, {
|
||||
method: "DELETE",
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then((res) => {
|
||||
show_message(res.message, res.ok);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -41,7 +41,20 @@
|
|||
(a
|
||||
("class" "button surface")
|
||||
("href" "/chats/{{ chat.id }}/pins")
|
||||
(text "{{ icon \"pin\" }} view pins")))
|
||||
(text "{{ icon \"pin\" }} view pins"))
|
||||
|
||||
; mute
|
||||
(text "{% if not user.id in chat.mutes -%}")
|
||||
(button
|
||||
("class" "button surface")
|
||||
("onclick" "mute_chat()")
|
||||
(text "{{ icon \"bell-off\" }} mute"))
|
||||
(text "{% else %}")
|
||||
(button
|
||||
("class" "button surface")
|
||||
("onclick" "unmute_chat()")
|
||||
(text "{{ icon \"bell-ring\" }} unmute"))
|
||||
(text "{%- endif %}"))
|
||||
|
||||
(ul
|
||||
(li (b (text "Chat name: ")) (span (text "{{ components::chat_name(chat=chat, members=members) }}")))
|
||||
|
@ -78,7 +91,10 @@
|
|||
("class" "flush flex items_center gap_ch")
|
||||
("href" "/@{{ member.username }}")
|
||||
(text "{{ components::avatar(id=member.id) }}")
|
||||
(text "{{ components::username(user=member) }}"))
|
||||
(text "{{ components::username(user=member) }}")
|
||||
(text "{% if member.id in chat.mutes -%}")
|
||||
(text "{{ icon \"bell-off\" }}")
|
||||
(text "{%- endif %}"))
|
||||
(span (text "{% if member.settings.status|length > 0 -%} {{ member.settings.status|markdown|safe }} {%- else -%} No status {%- endif %}"))
|
||||
(text "{% if is_owner -%}")
|
||||
(button
|
||||
|
@ -121,4 +137,5 @@
|
|||
(datalist ("id" "users_search"))
|
||||
|
||||
(script ("src" "/public/messages.js"))
|
||||
(script (text "STATE.chat_id = '{{ chat.id }}';"))
|
||||
(text "{% endblock %}")
|
||||
|
|
|
@ -17,6 +17,7 @@ impl DataManager {
|
|||
last_message_created: get!(x->4(i64)) as usize,
|
||||
last_message_read_by: serde_json::from_str(&get!(x->5(String))).unwrap(),
|
||||
pinned_messages: serde_json::from_str(&get!(x->6(String))).unwrap(),
|
||||
mutes: serde_json::from_str(&get!(x->7(String))).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,7 +122,7 @@ impl DataManager {
|
|||
|
||||
let res = execute!(
|
||||
&conn,
|
||||
"INSERT INTO t_chats VALUES ($1, $2, $3, $4, $5, $6, $7)",
|
||||
"INSERT INTO t_chats VALUES ($1, $2, $3, $4, $5, $6, $7, $8)",
|
||||
params![
|
||||
&(data.id as i64),
|
||||
&(data.created as i64),
|
||||
|
@ -130,6 +131,7 @@ impl DataManager {
|
|||
&(data.last_message_created as i64),
|
||||
&serde_json::to_string(&data.last_message_read_by).unwrap(),
|
||||
&serde_json::to_string(&data.pinned_messages).unwrap(),
|
||||
&serde_json::to_string(&data.mutes).unwrap(),
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -178,4 +180,5 @@ impl DataManager {
|
|||
auto_method!(update_chat_last_message_created(i64) -> "UPDATE t_chats SET last_message_created = $1 WHERE id = $2" --cache-key-tmpl="twny.chat:{}");
|
||||
auto_method!(update_chat_last_message_read_by(Vec<usize>) -> "UPDATE t_chats SET last_message_read_by = $1 WHERE id = $2" --serde --cache-key-tmpl="twny.chat:{}");
|
||||
auto_method!(update_chat_pinned_messages(Vec<usize>) -> "UPDATE t_chats SET pinned_messages = $1 WHERE id = $2" --serde --cache-key-tmpl="twny.chat:{}");
|
||||
auto_method!(update_chat_mutes(Vec<usize>) -> "UPDATE t_chats SET mutes = $1 WHERE id = $2" --serde --cache-key-tmpl="twny.chat:{}");
|
||||
}
|
||||
|
|
|
@ -4,5 +4,7 @@ CREATE TABLE IF NOT EXISTS t_chats (
|
|||
style TEXT NOT NULL,
|
||||
members TEXT NOT NULL,
|
||||
last_message_created BIGINT NOT NULL,
|
||||
last_message_read_by TEXT NOT NULL
|
||||
last_message_read_by TEXT NOT NULL,
|
||||
pinned_messages TEXT NOT NULL,
|
||||
mutes TEXT NOT NULL
|
||||
);
|
||||
|
|
|
@ -3,3 +3,6 @@ ALTER TABLE t_chats ADD COLUMN IF NOT EXISTS pinned_messages TEXT NOT NULL DEFAU
|
|||
|
||||
-- messages replying_to
|
||||
ALTER TABLE t_messages ADD COLUMN IF NOT EXISTS replying_to BIGINT NOT NULL DEFAULT 0;
|
||||
|
||||
-- chats mutes
|
||||
ALTER TABLE t_chats ADD COLUMN IF NOT EXISTS mutes TEXT NOT NULL DEFAULT '[]';
|
||||
|
|
|
@ -33,6 +33,7 @@ pub struct Chat {
|
|||
/// the UI and prevent every message showing a read receipt.
|
||||
pub last_message_read_by: Vec<usize>,
|
||||
pub pinned_messages: Vec<usize>,
|
||||
pub mutes: Vec<usize>,
|
||||
}
|
||||
|
||||
impl Chat {
|
||||
|
@ -46,6 +47,7 @@ impl Chat {
|
|||
last_message_created: 0,
|
||||
last_message_read_by: Vec::new(),
|
||||
pinned_messages: Vec::new(),
|
||||
mutes: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -580,3 +580,68 @@ pub async fn clear_chat_notifications(
|
|||
payload: (),
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn mute_request(
|
||||
jar: CookieJar,
|
||||
Extension(data): Extension<State>,
|
||||
Path(id): Path<usize>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data.2) {
|
||||
Some(x) => x,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
// ...
|
||||
let mut chat = match data.get_chat_by_id(id).await {
|
||||
Ok(x) => x,
|
||||
Err(e) => return Json(e.into()),
|
||||
};
|
||||
|
||||
if !chat.members.contains(&user.id) || chat.mutes.contains(&user.id) {
|
||||
return Json(Error::NotAllowed.into());
|
||||
}
|
||||
|
||||
chat.mutes.push(user.id);
|
||||
match data.update_chat_mutes(chat.id, chat.mutes).await {
|
||||
Ok(_) => Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: (),
|
||||
}),
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn unmute_request(
|
||||
jar: CookieJar,
|
||||
Extension(data): Extension<State>,
|
||||
Path(id): Path<usize>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data.2) {
|
||||
Some(x) => x,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
let mut chat = match data.get_chat_by_id(id).await {
|
||||
Ok(x) => x,
|
||||
Err(e) => return Json(e.into()),
|
||||
};
|
||||
|
||||
if !chat.members.contains(&user.id) || !chat.mutes.contains(&user.id) {
|
||||
return Json(Error::NotAllowed.into());
|
||||
}
|
||||
|
||||
chat.mutes
|
||||
.remove(chat.mutes.iter().position(|x| *x == user.id).unwrap());
|
||||
|
||||
match data.update_chat_mutes(chat.id, chat.mutes).await {
|
||||
Ok(_) => Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: (),
|
||||
}),
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ pub async fn create_request(
|
|||
|
||||
// update users
|
||||
for member in chat.members {
|
||||
if member == user.id {
|
||||
if member == user.id || chat.mutes.contains(&member) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@ pub fn routes() -> Router {
|
|||
"/chats/{id}/notifications",
|
||||
delete(chats::clear_chat_notifications),
|
||||
)
|
||||
.route("/chats/{id}/mute", post(chats::mute_request))
|
||||
.route("/chats/{id}/mute", delete(chats::unmute_request))
|
||||
// messages
|
||||
.route("/messages/{id}", post(messages::create_request))
|
||||
.route("/messages/{id}", delete(messages::delete_request))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue