merge reply view header with message page title bar
This commit is contained in:
@@ -1,4 +1,8 @@
|
|||||||
/* layout */
|
/* layout */
|
||||||
|
#chat-page #main #message-page[reply-view] .toolbar .title {
|
||||||
|
padding-left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
#chat-page #main #message-page .content {
|
#chat-page #main #message-page .content {
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
+147
-141
@@ -7,7 +7,6 @@ import * as React from "../../react";
|
|||||||
import MessagePageViewModel from "../../ViewModel/Pages/messagePageViewModel";
|
import MessagePageViewModel from "../../ViewModel/Pages/messagePageViewModel";
|
||||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||||
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
|
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
|
||||||
import {ReplyViewHeader} from "../Components/replyViewHeader";
|
|
||||||
|
|
||||||
export function MessagePage(
|
export function MessagePage(
|
||||||
coreViewModel: CoreViewModel,
|
coreViewModel: CoreViewModel,
|
||||||
@@ -16,148 +15,155 @@ export function MessagePage(
|
|||||||
messagePageViewModel.loadData();
|
messagePageViewModel.loadData();
|
||||||
|
|
||||||
const ChatMessageViewModelToView: React.StateItemConverter<
|
const ChatMessageViewModelToView: React.StateItemConverter<
|
||||||
ChatMessageViewModel
|
ChatMessageViewModel
|
||||||
> = (chatMessageViewModel: ChatMessageViewModel) => {
|
> = (chatMessageViewModel: ChatMessageViewModel) => {
|
||||||
return ChatMessage(coreViewModel, chatMessageViewModel);
|
return ChatMessage(coreViewModel, chatMessageViewModel);
|
||||||
};
|
};
|
||||||
|
|
||||||
const messageContainer = (
|
const messageContainer = (
|
||||||
<div
|
<div
|
||||||
id="message-container"
|
id="message-container"
|
||||||
children:append={[
|
children:append={[
|
||||||
messagePageViewModel.filteredMessageViewModels,
|
messagePageViewModel.filteredMessageViewModels,
|
||||||
ChatMessageViewModelToView,
|
ChatMessageViewModelToView,
|
||||||
]}
|
]}
|
||||||
></div>
|
></div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const persistenceId = messagePageViewModel.chatViewModel.chatModel.id;
|
const persistenceId = messagePageViewModel.chatViewModel.chatModel.id;
|
||||||
const replyPreview = ViewController.inlineReplies.setState(
|
const replyPreview = ViewController.inlineReplies.setState(
|
||||||
persistenceId,
|
persistenceId,
|
||||||
() =>
|
() =>
|
||||||
React.createProxyState(
|
React.createProxyState(
|
||||||
[messagePageViewModel.replyingMessage],
|
[messagePageViewModel.replyingMessage],
|
||||||
() => {
|
() => {
|
||||||
if (messagePageViewModel.replyingMessage.value == undefined)
|
if (messagePageViewModel.replyingMessage.value == undefined)
|
||||||
return <div></div>;
|
return <div></div>;
|
||||||
return ReplyPreview(
|
return ReplyPreview(
|
||||||
coreViewModel,
|
coreViewModel,
|
||||||
messagePageViewModel.replyingMessage.value,
|
messagePageViewModel.replyingMessage.value,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
function scrollDown(hard: boolean = false) {
|
function scrollDown(hard: boolean = false) {
|
||||||
if (hard) {
|
if (hard) {
|
||||||
messageContainer.setAttribute("scroll-hard", "");
|
messageContainer.setAttribute("scroll-hard", "");
|
||||||
}
|
|
||||||
messageContainer.scrollTop = messageContainer.scrollHeight;
|
|
||||||
messageContainer.removeAttribute("scroll-hard");
|
|
||||||
}
|
}
|
||||||
function scrollDownIfApplicable() {
|
messageContainer.scrollTop = messageContainer.scrollHeight;
|
||||||
const scrollFromBottom =
|
messageContainer.removeAttribute("scroll-hard");
|
||||||
messageContainer.scrollHeight -
|
}
|
||||||
(messageContainer.scrollTop + messageContainer.offsetHeight);
|
function scrollDownIfApplicable() {
|
||||||
if (scrollFromBottom > 400) return;
|
const scrollFromBottom =
|
||||||
|
messageContainer.scrollHeight -
|
||||||
scrollDown();
|
(messageContainer.scrollTop + messageContainer.offsetHeight);
|
||||||
}
|
if (scrollFromBottom > 400) return;
|
||||||
messagePageViewModel.filteredMessageViewModels.subscribeSilent(
|
|
||||||
scrollDownIfApplicable,
|
scrollDown();
|
||||||
);
|
}
|
||||||
messagePageViewModel.replyViewSelectedMessage.subscribeSilent(selectedMessage => {
|
messagePageViewModel.filteredMessageViewModels.subscribeSilent(
|
||||||
if (selectedMessage != undefined) return;
|
scrollDownIfApplicable,
|
||||||
setTimeout(scrollDown, 100);
|
);
|
||||||
})
|
messagePageViewModel.replyViewSelectedMessage.subscribeSilent(selectedMessage => {
|
||||||
setTimeout(() => scrollDown(true), 100);
|
if (selectedMessage != undefined) return;
|
||||||
|
setTimeout(scrollDown, 100);
|
||||||
messagePageViewModel.focusSetter.subscribeSilent(() => {
|
})
|
||||||
ViewController.setFocusWithDelay();
|
setTimeout(() => scrollDown(true), 100);
|
||||||
});
|
|
||||||
|
messagePageViewModel.focusSetter.subscribeSilent(() => {
|
||||||
const isInReplyView = React.createProxyState([messagePageViewModel.replyViewSelectedMessage], ()=>messagePageViewModel.replyViewSelectedMessage.value != undefined);
|
ViewController.setFocusWithDelay();
|
||||||
|
});
|
||||||
return (
|
|
||||||
<div id="message-page" toggle:reply-view={isInReplyView}>
|
const isInReplyView = React.createProxyState([messagePageViewModel.replyViewSelectedMessage], ()=>messagePageViewModel.replyViewSelectedMessage.value != undefined);
|
||||||
<div class="pane-wrapper">
|
|
||||||
<div class="pane">
|
const title = React.createProxyState([messagePageViewModel.isReplyViewActive], ()=>messagePageViewModel.isReplyViewActive.value ? coreViewModel.translations.chatPage.message.replyHeaderLabel(messagePageViewModel.replyViewSelectedMessage.value.body.value) : coreViewModel.translations.chatPage.message.messagesHeadline);
|
||||||
<div class="toolbar">
|
|
||||||
<span class="title">
|
return (
|
||||||
{
|
<div id="message-page" toggle:reply-view={isInReplyView}>
|
||||||
coreViewModel.translations.chatPage.message
|
<div class="pane-wrapper">
|
||||||
.messagesHeadline
|
<div class="pane">
|
||||||
}
|
<div class="toolbar">
|
||||||
</span>
|
<button
|
||||||
<span>
|
class="ghost"
|
||||||
<button
|
on:click={messagePageViewModel.resetReplyView}
|
||||||
class="ghost inset-outline"
|
toggle:hidden={messagePageViewModel.isReplyViewInactive}
|
||||||
on:click={messagePageViewModel.showFilterModal}
|
>
|
||||||
aria-label={
|
<span class="icon">arrow_back</span>
|
||||||
coreViewModel.translations.chatPage.message
|
</button>
|
||||||
.filterMessagesButtonAudioLabel
|
<span
|
||||||
}
|
class="title ellipsis width-100 flex"
|
||||||
toggle:selected={
|
subscribe:innerText={title}
|
||||||
messagePageViewModel.isFilterActive
|
>
|
||||||
}
|
</span>
|
||||||
>
|
<span>
|
||||||
<span class="icon">filter_alt</span>
|
<button
|
||||||
</button>
|
class="ghost inset-outline"
|
||||||
</span>
|
on:click={messagePageViewModel.showFilterModal}
|
||||||
</div>
|
aria-label={
|
||||||
<div class="content">
|
coreViewModel.translations.chatPage.message
|
||||||
{ReplyViewHeader(coreViewModel, messagePageViewModel)}
|
.filterMessagesButtonAudioLabel
|
||||||
{messageContainer}
|
}
|
||||||
<div id="composer">
|
toggle:selected={
|
||||||
<div class="content-width-constraint">
|
messagePageViewModel.isFilterActive
|
||||||
<div
|
}
|
||||||
class="reply-preview-wrapper"
|
>
|
||||||
children:set={replyPreview}
|
<span class="icon">filter_alt</span>
|
||||||
></div>
|
</button>
|
||||||
<div class="input-width-constraint">
|
</span>
|
||||||
<input
|
</div>
|
||||||
id="focused"
|
<div class="content">
|
||||||
class="blur"
|
{messageContainer}
|
||||||
bind:value={
|
<div id="composer">
|
||||||
messagePageViewModel.composingMessage
|
<div class="content-width-constraint">
|
||||||
}
|
<div
|
||||||
on:enter={
|
class="reply-preview-wrapper"
|
||||||
messagePageViewModel.sendMessage
|
children:set={replyPreview}
|
||||||
}
|
></div>
|
||||||
placeholder={
|
<div class="input-width-constraint">
|
||||||
coreViewModel.translations.chatPage
|
<input
|
||||||
.message
|
id="focused"
|
||||||
.composerInputPlaceholder
|
class="blur"
|
||||||
}
|
bind:value={
|
||||||
></input>
|
messagePageViewModel.composingMessage
|
||||||
<button
|
}
|
||||||
class="primary blur"
|
on:enter={
|
||||||
aria-label={
|
messagePageViewModel.sendMessage
|
||||||
coreViewModel.translations.chatPage
|
}
|
||||||
.message
|
placeholder={
|
||||||
.sendMessageButtonAudioLabel
|
coreViewModel.translations.chatPage
|
||||||
}
|
.message
|
||||||
on:click={
|
.composerInputPlaceholder
|
||||||
messagePageViewModel.sendMessage
|
}
|
||||||
}
|
></input>
|
||||||
toggle:disabled={
|
<button
|
||||||
messagePageViewModel.cannotSendMessage
|
class="primary blur"
|
||||||
}
|
aria-label={
|
||||||
>
|
coreViewModel.translations.chatPage
|
||||||
<span class="icon">send</span>
|
.message
|
||||||
</button>
|
.sendMessageButtonAudioLabel
|
||||||
</div>
|
}
|
||||||
</div>
|
on:click={
|
||||||
</div>
|
messagePageViewModel.sendMessage
|
||||||
</div>
|
}
|
||||||
</div>
|
toggle:disabled={
|
||||||
</div>
|
messagePageViewModel.cannotSendMessage
|
||||||
|
}
|
||||||
{MessageFilterModal(
|
>
|
||||||
coreViewModel,
|
<span class="icon">send</span>
|
||||||
messagePageViewModel,
|
</button>
|
||||||
ChatMessageViewModelToView,
|
</div>
|
||||||
)}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{MessageFilterModal(
|
||||||
|
coreViewModel,
|
||||||
|
messagePageViewModel,
|
||||||
|
ChatMessageViewModelToView,
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ const englishTranslations = {
|
|||||||
//
|
//
|
||||||
|
|
||||||
replyPrefixLabel: "Replies: ",
|
replyPrefixLabel: "Replies: ",
|
||||||
replyHeaderLabel: (sender: string) => `Replies to ${sender}`,
|
replyHeaderLabel: (message: string) => `Replies to "${message}"`,
|
||||||
},
|
},
|
||||||
|
|
||||||
task: {
|
task: {
|
||||||
@@ -576,7 +576,7 @@ export const allTranslations: {
|
|||||||
questionReaction: "Reaktion: Fragezeichen",
|
questionReaction: "Reaktion: Fragezeichen",
|
||||||
|
|
||||||
replyPrefixLabel: "Antworten: ",
|
replyPrefixLabel: "Antworten: ",
|
||||||
replyHeaderLabel: (sender: string) => `Antworten an ${sender}`,
|
replyHeaderLabel: (message: string) => `Antworten an "${message}"`,
|
||||||
},
|
},
|
||||||
|
|
||||||
task: {
|
task: {
|
||||||
@@ -881,7 +881,7 @@ export const allTranslations: {
|
|||||||
questionReaction: "Reaccion: signo de interrogación",
|
questionReaction: "Reaccion: signo de interrogación",
|
||||||
|
|
||||||
replyPrefixLabel: "Respuestas: ",
|
replyPrefixLabel: "Respuestas: ",
|
||||||
replyHeaderLabel: (sender: string) => `Respuestas a ${sender}`,
|
replyHeaderLabel: (message: string) => `Respuestas a "${message}"`,
|
||||||
},
|
},
|
||||||
|
|
||||||
task: {
|
task: {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export default class MessagePageViewModel extends Context {
|
|||||||
new React.ListState();
|
new React.ListState();
|
||||||
replyViewSelectedMessage: React.State<ChatMessageViewModel|undefined> = new React.State(undefined);
|
replyViewSelectedMessage: React.State<ChatMessageViewModel|undefined> = new React.State(undefined);
|
||||||
isReplyViewActive: React.State<boolean> = React.createProxyState([this.replyViewSelectedMessage], ()=>this.replyViewSelectedMessage.value != undefined);
|
isReplyViewActive: React.State<boolean> = React.createProxyState([this.replyViewSelectedMessage], ()=>this.replyViewSelectedMessage.value != undefined);
|
||||||
|
isReplyViewInactive = React.createProxyState([this.isReplyViewActive], ()=>!this.isReplyViewActive.value);
|
||||||
searchViewModel: SearchViewModel<ChatMessageViewModel>;
|
searchViewModel: SearchViewModel<ChatMessageViewModel>;
|
||||||
isFilterModalOpen = new React.State<boolean>(false);
|
isFilterModalOpen = new React.State<boolean>(false);
|
||||||
reactionFilter = new React.State<ReactionSymbols | undefined>(undefined);
|
reactionFilter = new React.State<ReactionSymbols | undefined>(undefined);
|
||||||
|
|||||||
Reference in New Issue
Block a user