(feat): add message states, tweaks chat ui
All checks were successful
/ build-web (push) Successful in 1m10s
/ build-desktop (push) Successful in 11m22s
/ build-mobile (push) Successful in 15m52s
/ release (push) Successful in 23s

(feat): add drag and drop to login page
This commit is contained in:
Alois 2026-05-24 14:09:57 +02:00
commit 67b7926dab
9 changed files with 226 additions and 49 deletions

View file

@ -35,6 +35,7 @@ function MessageComponent({
return (
<div
// pt-3 is to get a gap between messages
className={`${grouped ? "" : "pt-3"} w-full flex justify-start transition-opacity duration-150 ${actuallyFailed || message.message_state === "awaiting" ? "opacity-50" : ""}`}
>
<ContextMenu>

View file

@ -438,7 +438,7 @@ export default function Screen() {
className="min-h-0 flex-1 overflow-y-auto"
style={{
overflowAnchor: "none",
paddingBottom: "8px",
paddingBottom: "22px",
}}
onScroll={handleContainerScroll}
>
@ -461,7 +461,6 @@ export default function Screen() {
left: 0,
width: "100%",
transform: `translateY(${virtualRow.start + verticalOffset}px)`,
padding: "4px 0",
}}
>
<div className="w-full flex justify-start">

View file

@ -23,7 +23,7 @@ function reduceDisplay(display: string) {
}
export default function Provider(props: { children: React.ReactNode }) {
const { subscribePush } = useTTP();
const { subscribePush, send } = useTTP();
const { load } = useStorage();
const { get } = useUser();
const { decryptText, getSharedSecret } = useCrypto();
@ -49,7 +49,32 @@ export default function Provider(props: { children: React.ReactNode }) {
message.content,
);
console.log(userId, sender_id, userId === sender_id);
// Update message state
if (
(await load("settings.read_confirmations")) &&
userId === sender_id
) {
await send(
"message_state",
{
message_state: "read",
},
{
id: ttpMessage.id,
},
);
} else {
await send(
"message_state",
{
message_state: "received",
},
{
id: ttpMessage.id,
},
);
}
if (userId === sender_id) {
addLiveMessage({
...message,
@ -60,7 +85,7 @@ export default function Provider(props: { children: React.ReactNode }) {
return;
}
// add notification symbol to conversation cards
// todo: add notification symbol to conversation cards (incl. message start)
moveUserIdToTop(sender_id);
@ -91,6 +116,7 @@ export default function Provider(props: { children: React.ReactNode }) {
addLiveMessage,
userId,
moveUserIdToTop,
send,
]);
return (

View file

@ -167,11 +167,17 @@ export const ttp = {
response: z.object({}),
},
message_state: {
request: z.object({
chat_partner_id: z.number(),
send_time: z.number(),
message_state: message.shape.message_state,
}),
request: z
.object({
chat_partner_id: z.number(),
send_time: z.number(),
message_state: message.shape.message_state,
})
.or(
z.object({
message_state: message.shape.message_state,
}),
),
response: z.object({
chat_partner_id: z.number(),
message_state: message.shape.message_state,

View file

@ -28,6 +28,21 @@ const settings = {
type: "boolean",
default: false,
},
read_confirmations: {
display: "Enable Read Confirmations",
type: "boolean",
default: true,
},
receive_confirmations: {
display: "Enable Receive Confirmations",
type: "boolean",
default: true,
},
show_start_of_last_message_in_sidebar: {
display: "Show Start of Last Message in Sidebar",
type: "boolean",
default: true,
},
},
},
application: {
@ -35,6 +50,7 @@ const settings = {
},
} as const satisfies SettingsSchema;
// Assemble storage defaults
export default settings;
type BooleanSettingNames<T extends SettingsSchema> = {