merge reply view header with message page title bar

This commit is contained in:
marlon-erler
2026-09-24 15:16:13 +02:00
parent 5ea256a2fa
commit 4deedf781a
5 changed files with 940 additions and 1096 deletions
+785 -952
View File
File diff suppressed because it is too large Load Diff
+4
View File
@@ -1,4 +1,8 @@
/* layout */
#chat-page #main #message-page[reply-view] .toolbar .title {
padding-left: 0px;
}
#chat-page #main #message-page .content {
padding: 0px;
overflow: hidden;
+34 -28
View File
@@ -7,7 +7,6 @@ import * as React from "../../react";
import MessagePageViewModel from "../../ViewModel/Pages/messagePageViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
import {ReplyViewHeader} from "../Components/replyViewHeader";
export function MessagePage(
coreViewModel: CoreViewModel,
@@ -17,11 +16,11 @@ export function MessagePage(
const ChatMessageViewModelToView: React.StateItemConverter<
ChatMessageViewModel
> = (chatMessageViewModel: ChatMessageViewModel) => {
> = (chatMessageViewModel: ChatMessageViewModel) => {
return ChatMessage(coreViewModel, chatMessageViewModel);
};
};
const messageContainer = (
const messageContainer = (
<div
id="message-container"
children:append={[
@@ -29,10 +28,10 @@ export function MessagePage(
ChatMessageViewModelToView,
]}
></div>
);
);
const persistenceId = messagePageViewModel.chatViewModel.chatModel.id;
const replyPreview = ViewController.inlineReplies.setState(
const persistenceId = messagePageViewModel.chatViewModel.chatModel.id;
const replyPreview = ViewController.inlineReplies.setState(
persistenceId,
() =>
React.createProxyState(
@@ -46,48 +45,56 @@ export function MessagePage(
);
},
),
);
);
function scrollDown(hard: boolean = false) {
function scrollDown(hard: boolean = false) {
if (hard) {
messageContainer.setAttribute("scroll-hard", "");
}
messageContainer.scrollTop = messageContainer.scrollHeight;
messageContainer.removeAttribute("scroll-hard");
}
function scrollDownIfApplicable() {
}
function scrollDownIfApplicable() {
const scrollFromBottom =
messageContainer.scrollHeight -
(messageContainer.scrollTop + messageContainer.offsetHeight);
if (scrollFromBottom > 400) return;
scrollDown();
}
messagePageViewModel.filteredMessageViewModels.subscribeSilent(
}
messagePageViewModel.filteredMessageViewModels.subscribeSilent(
scrollDownIfApplicable,
);
messagePageViewModel.replyViewSelectedMessage.subscribeSilent(selectedMessage => {
);
messagePageViewModel.replyViewSelectedMessage.subscribeSilent(selectedMessage => {
if (selectedMessage != undefined) return;
setTimeout(scrollDown, 100);
})
setTimeout(() => scrollDown(true), 100);
})
setTimeout(() => scrollDown(true), 100);
messagePageViewModel.focusSetter.subscribeSilent(() => {
messagePageViewModel.focusSetter.subscribeSilent(() => {
ViewController.setFocusWithDelay();
});
});
const isInReplyView = React.createProxyState([messagePageViewModel.replyViewSelectedMessage], ()=>messagePageViewModel.replyViewSelectedMessage.value != undefined);
const isInReplyView = React.createProxyState([messagePageViewModel.replyViewSelectedMessage], ()=>messagePageViewModel.replyViewSelectedMessage.value != undefined);
return (
const title = React.createProxyState([messagePageViewModel.isReplyViewActive], ()=>messagePageViewModel.isReplyViewActive.value ? coreViewModel.translations.chatPage.message.replyHeaderLabel(messagePageViewModel.replyViewSelectedMessage.value.body.value) : coreViewModel.translations.chatPage.message.messagesHeadline);
return (
<div id="message-page" toggle:reply-view={isInReplyView}>
<div class="pane-wrapper">
<div class="pane">
<div class="toolbar">
<span class="title">
{
coreViewModel.translations.chatPage.message
.messagesHeadline
}
<button
class="ghost"
on:click={messagePageViewModel.resetReplyView}
toggle:hidden={messagePageViewModel.isReplyViewInactive}
>
<span class="icon">arrow_back</span>
</button>
<span
class="title ellipsis width-100 flex"
subscribe:innerText={title}
>
</span>
<span>
<button
@@ -106,7 +113,6 @@ export function MessagePage(
</span>
</div>
<div class="content">
{ReplyViewHeader(coreViewModel, messagePageViewModel)}
{messageContainer}
<div id="composer">
<div class="content-width-constraint">
@@ -159,5 +165,5 @@ export function MessagePage(
ChatMessageViewModelToView,
)}
</div>
);
);
}
+3 -3
View File
@@ -252,7 +252,7 @@ const englishTranslations = {
//
replyPrefixLabel: "Replies: ",
replyHeaderLabel: (sender: string) => `Replies to ${sender}`,
replyHeaderLabel: (message: string) => `Replies to "${message}"`,
},
task: {
@@ -576,7 +576,7 @@ export const allTranslations: {
questionReaction: "Reaktion: Fragezeichen",
replyPrefixLabel: "Antworten: ",
replyHeaderLabel: (sender: string) => `Antworten an ${sender}`,
replyHeaderLabel: (message: string) => `Antworten an "${message}"`,
},
task: {
@@ -881,7 +881,7 @@ export const allTranslations: {
questionReaction: "Reaccion: signo de interrogación",
replyPrefixLabel: "Respuestas: ",
replyHeaderLabel: (sender: string) => `Respuestas a ${sender}`,
replyHeaderLabel: (message: string) => `Respuestas a "${message}"`,
},
task: {
@@ -18,6 +18,7 @@ export default class MessagePageViewModel extends Context {
new React.ListState();
replyViewSelectedMessage: React.State<ChatMessageViewModel|undefined> = new React.State(undefined);
isReplyViewActive: React.State<boolean> = React.createProxyState([this.replyViewSelectedMessage], ()=>this.replyViewSelectedMessage.value != undefined);
isReplyViewInactive = React.createProxyState([this.isReplyViewActive], ()=>!this.isReplyViewActive.value);
searchViewModel: SearchViewModel<ChatMessageViewModel>;
isFilterModalOpen = new React.State<boolean>(false);
reactionFilter = new React.State<ReactionSymbols | undefined>(undefined);