add: chat pins

This commit is contained in:
trisua 2025-09-03 17:12:26 -04:00
parent 9546c580e7
commit 82eafdadb3
21 changed files with 330 additions and 56 deletions

View file

@ -326,3 +326,27 @@ function create_direct_chat_with_user(id) {
}
});
}
function pin_message(e, id) {
fetch(`/api/v1/chats/${STATE.chat_id}/pins/${id}`, {
method: "POST",
})
.then((res) => res.json())
.then((res) => {
show_message(res.message, res.ok);
if (res.ok) {
e.target.remove();
}
});
}
function unpin_message(id) {
fetch(`/api/v1/chats/${STATE.chat_id}/pins/${id}`, {
method: "DELETE",
})
.then((res) => res.json())
.then((res) => {
show_message(res.message, res.ok);
});
}

View file

@ -116,6 +116,10 @@ article {
height: 100%;
}
.tabs {
overflow: auto;
}
.fadein {
animation: fadein ease-in-out 1 0.5s forwards running;
}
@ -801,6 +805,7 @@ menu.col {
background: var(--color-surface);
color: var(--color-text);
border-radius: var(--radius);
min-height: 36px;
}
.message.mine .body {
@ -812,3 +817,8 @@ menu.col {
.message:not(.mine) .body {
border-bottom-left-radius: 0;
}
.message:hover .dropdown.hidden,
.message:focus .dropdown.hidden {
display: flex !important;
}

View file

@ -9,7 +9,7 @@
(a
("class" "button tab camo")
("href" "/chats")
(text "chats")
(text "{{ icon \"castle\" }} chats")
(text "{% if user.missed_messages_count > 0 -%}") (b (text "({{ user.missed_messages_count }})")) (text "{%- endif %}"))
(a
("class" "button tab")
@ -18,7 +18,7 @@
(a
("class" "button tab camo")
("href" "/chats/{{ chat.id }}/manage")
(text "{{ icon \"settings-2\" }} Manage"))))
(text "{{ icon \"settings-2\" }} manage"))))
(div
("class" "flex flex_col card_nest reverse")
("style" "flex: 1 0 auto")
@ -29,10 +29,6 @@
("class" "card flex flex_rev_col gap_2")
("style" "flex: 1 0 auto")
("id" "messages_stream")
(text "{% if messages|length == 0 -%}")
(i ("class" "flex gap_ch items_center fade") (text "{{ icon \"star\" }} This is the start of the chat!"))
(text "{%- endif %}")
(div ("ui_ident" "data_marker")))
(div ("id" "read_receipt_zone") ("class" "card") ("style" "min-height: 32.5px; position: sticky; bottom: 0")))
(form
@ -57,5 +53,5 @@
setTimeout(() => {
scroll_bottom();
}, 500);"))
}, 1500);"))
(text "{% endblock %}")

View file

@ -9,7 +9,7 @@
(a
("class" "button tab")
("href" "/chats")
(text "chats")
(text "{{ icon \"castle\" }} chats")
(text "{% if user.missed_messages_count > 0 -%}") (b (text "({{ user.missed_messages_count }})")) (text "{%- endif %}")))
(button
("class" "button square")

View file

@ -41,20 +41,27 @@
(text "{%- endif %}")
(text "{%- endmacro %}")
(text "{% macro message(message) -%}")
(text "{% macro message(message, is_pinned=false) -%}")
(div
("class" "flex w_full gap_ch message {%- if user.id == message.owner %} justify_right mine {%- endif %}")
("id" "message_{{ message.id }}")
(text "{% if message.owner == user.id -%}")
(div
("class" "dropdown")
("class" "dropdown hidden")
(button
("onclick" "open_dropdown(event)")
("exclude" "dropdown")
("class" "button")
("class" "button icon_only big_icon")
(text "{{ icon \"ellipsis\" }}"))
(div
("class" "inner surface")
(text "{% if not is_pinned -%}")
(button
("class" "button surface")
("onclick" "pin_message(event, '{{ message.id }}')")
(text "pin"))
(text "{%- endif %}")
(text "{% if message.owner == user.id -%}")
(button
("class" "button surface")
("onclick" "edit_message_ui('{{ message.id }}')")
@ -62,8 +69,8 @@
(button
("class" "button surface red")
("onclick" "delete_message('{{ message.id }}')")
(text "delete"))))
(text "{%- endif %}")
(text "delete"))
(text "{%- endif %}")))
(div
("class" "body no_p_margin")

View file

@ -9,7 +9,7 @@
(a
("class" "button tab camo")
("href" "/chats")
(text "chats"))
(text "{{ icon \"castle\" }} chats"))
(a
("class" "button tab camo")
("href" "/chats/{{ chat.id }}")
@ -17,24 +17,31 @@
(a
("class" "button tab")
("href" "/chats/{{ chat.id }}/manage")
(text "{{ icon \"settings-2\" }} Manage"))))
(text "{{ icon \"settings-2\" }} manage"))))
(div
("class" "flex flex_col gap_4 card")
("style" "flex: 1 0 auto")
(text "{% if chat.style != \"Direct\" -%}")
; gc only
(button
("class" "button surface")
("onclick" "rename_chat('{{ chat.id }}', GC_INFO)")
(text "{{ icon \"pencil\" }} rename chat"))
(div
("class" "flex gap_2 flex_wrap")
(text "{% if chat.style != \"Direct\" -%}")
; gc only
(button
("class" "button surface")
("onclick" "rename_chat('{{ chat.id }}', GC_INFO)")
(text "{{ icon \"pencil\" }} rename chat"))
(script
("type" "application/json")
("id" "gc_info")
(text "{{ chat.style.Group|json_encode() }}"))
(script
(text "globalThis.GC_INFO = JSON.parse(document.getElementById(\"gc_info\").innerHTML)"))
(text "{%- endif %}")
(script
("type" "application/json")
("id" "gc_info")
(text "{{ chat.style.Group|json_encode() }}"))
(script
(text "globalThis.GC_INFO = JSON.parse(document.getElementById(\"gc_info\").innerHTML)"))
(text "{%- endif %}")
; every chat
(a
("class" "button surface")
("href" "/chats/{{ chat.id }}/pins")
(text "{{ icon \"pin\" }} view pins")))
(ul
(li (b (text "Chat name: ")) (span (text "{{ components::chat_name(chat=chat, members=members) }}")))

View file

@ -1,6 +1,6 @@
(text "{%- import \"components.lisp\" as components -%}")
(text "{% for message in messages -%}")
(text "{{ components::message(message=message) }}")
(text "{{ components::message(message=message, is_pinned=message.id in pins) }}")
(text "{%- endfor %}")
(div
@ -12,4 +12,5 @@
(div
("class" "hidden")
("id" "msgs_quit_{{ id }}"))
(i ("class" "flex gap_ch items_center fade") (text "{{ icon \"star\" }} This is the start of the chat!"))
(text "{%- endif %}")

View file

@ -0,0 +1,36 @@
(text "{% extends \"root.lisp\" %} {% block head %}")
(title
(text "Pins in {{ components::chat_name(chat=chat, members=members) }} — {{ config.name }}"))
(text "{% endblock %} {% block body %}")
(div
("class" "flex w_full gap_2 justify_between items_center")
(div
("class" "tabs short bar flex")
(a
("class" "button tab camo")
("href" "/chats")
(text "{{ icon \"castle\" }} chats"))
(a
("class" "button tab camo")
("href" "/chats/{{ chat.id }}")
(text "{{ components::chat_name(chat=chat, members=members, advanced=true, avatar_size=\"18px\") }}"))
(a
("class" "button tab")
("href" "/chats/{{ chat.id }}/manage")
(text "{{ icon \"settings-2\" }} manage"))))
(div
("class" "flex flex_col gap_4 card")
("style" "flex: 1 0 auto")
(p (text "Using ") (b (text "{{ messages|length }} ")) (text "of ") (b (text "12 ")) (text "pins."))
(text "{% for message in messages -%}")
(hr)
(button
("class" "button surface red")
("onclick" "unpin_message('{{ message.id }}')")
(text "unpin"))
(text "{{ components::message(message=message) }}")
(text "{%- endfor %}"))
(script ("src" "/public/messages.js"))
(script (text "STATE.chat_id = '{{ chat.id }}';"))
(text "{% endblock %}")

View file

@ -134,7 +134,9 @@
}
.profile .banner {
background: url(\"{{ config.service_hosts.buckets }}/banners/{{ profile.id }}\") no-repeat center !important;
background-image: url(\"{{ config.service_hosts.buckets }}/banners/{{ profile.id }}\") !important;
background-repeat: no-repeat !important;
background-position: center !important;
background-size: cover !important;
border-radius: var(--radius) var(--radius) 0 0;
height: 225px;