add message filter

This commit is contained in:
marlon-erler
2026-04-11 19:26:13 +00:00
parent dde9214e34
commit 423e84bc14
8 changed files with 217 additions and 113 deletions
+8
View File
@@ -149,6 +149,14 @@
word-break: break-word;
}
.modal .message-bubble .tile.main .body {
word-break: keep-all;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
}
.message-bubble[sentbyuser] {
justify-content: flex-end;
}
+24 -2
View File
@@ -6,6 +6,7 @@ import MessagePageViewModel from "../../ViewModel/Pages/messagePageViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
import { ChatMessage } from "../Components/chatMessage";
import { SearchModal } from "../Modals/searchModal";
export function MessagePage(
coreViewModel: CoreViewModel,
@@ -22,7 +23,7 @@ export function MessagePage(
<div
id="message-container"
children:append={[
messagePageViewModel.chatMessageViewModels,
messagePageViewModel.filteredMessageViewModels,
ChatMessageViewModelToView,
]}
></div>
@@ -43,7 +44,7 @@ export function MessagePage(
scrollDown();
}
messagePageViewModel.chatMessageViewModels.subscribeSilent(
messagePageViewModel.filteredMessageViewModels.subscribeSilent(
scrollDownIfApplicable,
);
setTimeout(() => scrollDown(true), 100);
@@ -59,6 +60,18 @@ export function MessagePage(
.messagesHeadline
}
</span>
<span>
<button
class="ghost"
on:click={messagePageViewModel.openFilterModal}
aria-label={
coreViewModel.translations.chatPage.message
.filterMessagesButtonAudioLabel
}
>
<span class="icon">filter_alt</span>
</button>
</span>
</div>
<div class="content">
{messageContainer}
@@ -100,6 +113,15 @@ export function MessagePage(
</div>
</div>
</div>
{SearchModal(
coreViewModel,
messagePageViewModel.searchViewModel,
coreViewModel.translations.chatPage.message
.messageFilterHeadline,
ChatMessageViewModelToView,
messagePageViewModel.isFilterModalOpen,
)}
</div>
);
}
@@ -13,7 +13,10 @@ export function MessageReactionButton(
) {
let audioLabel: string;
let count: React.State<number>;
let isActive = React.createProxyState([chatMessageViewModel.userReaction], (() => chatMessageViewModel.userReaction.value == content))
let isActive = React.createProxyState(
[chatMessageViewModel.userReaction],
() => chatMessageViewModel.userReaction.value == content,
);
function sendReaction() {
chatMessageViewModel.sendReaction(content, isActive.value);
+6
View File
@@ -184,11 +184,13 @@ const englishTranslations = {
message: {
messagesHeadline: "Messages",
messageFilterHeadline: "Filter messages",
///
composerInputPlaceholder: "Type a message...",
sendMessageButtonAudioLabel: "send message",
filterMessagesButtonAudioLabel: "filter messages",
///
@@ -480,9 +482,11 @@ export const allTranslations: {
message: {
messagesHeadline: "Nachrichten",
messageFilterHeadline: "Nachrichten filtern",
composerInputPlaceholder: "Schreib eine Nachricht...",
sendMessageButtonAudioLabel: "nachricht senden",
filterMessagesButtonAudioLabel: "nachrichten filtern",
showMessageInfoButtonAudioLabel: "nachrichteninfo anzeigen",
messageInfoHeadline: "Nachrichteninfo",
@@ -750,9 +754,11 @@ export const allTranslations: {
message: {
messagesHeadline: "Mensajes",
messageFilterHeadline: "Filtrar mensajes",
composerInputPlaceholder: "Escribe un mensaje...",
sendMessageButtonAudioLabel: "enviar mensaje",
filterMessagesButtonAudioLabel: "filtrar mensajes",
showMessageInfoButtonAudioLabel:
"mostrar información del mensaje",
+8 -3
View File
@@ -23,7 +23,9 @@ export default class ChatMessageViewModel {
sentByUser: boolean;
allReactions = new React.MapState<ChatMessageReaction>();
userReaction = new React.State<ReactionSymbols | string | undefined>(undefined);
userReaction = new React.State<ReactionSymbols | string | undefined>(
undefined,
);
reactionsThumbsUp = React.MapState<ChatMessageReaction>;
reactionsCheck = React.MapState<ChatMessageReaction>;
reactionsStop = React.MapState<ChatMessageReaction>;
@@ -93,8 +95,11 @@ export default class ChatMessageViewModel {
this.allReactions.set(reaction.sender, reaction);
}
if (reaction.sender != this.coreViewModel.settingsModel.username) return;
this.userReaction.value = reaction.isDeleting ? undefined : reaction.content;
if (reaction.sender != this.coreViewModel.settingsModel.username)
return;
this.userReaction.value = reaction.isDeleting
? undefined
: reaction.content;
};
sendReaction = (content: ReactionSymbols, isDeleting: boolean): void => {
@@ -8,11 +8,16 @@ import {
import ChatMessageViewModel from "../Chat/chatMessageViewModel";
import ChatViewModel from "../Chat/chatViewModel";
import CoreViewModel from "../Global/coreViewModel";
import SearchViewModel from "../Utility/searchViewModel";
export default class MessagePageViewModel {
// state
chatMessageViewModels: React.MapState<ChatMessageViewModel> =
new React.MapState();
filteredMessageViewModels: React.ListState<ChatMessageViewModel> =
new React.ListState();
searchViewModel: SearchViewModel<ChatMessageViewModel>;
isFilterModalOpen = new React.State<boolean>(false);
composingMessage: React.State<string> = new React.State("");
// guards
@@ -81,6 +86,10 @@ export default class MessagePageViewModel {
messageViewModel.handleReaction(reaction);
};
openFilterModal = (): void => {
this.isFilterModalOpen.value = true;
};
// load
loadData = (): void => {
this.chatMessageViewModels.clear();
@@ -106,5 +115,12 @@ export default class MessagePageViewModel {
this.chatViewModel.settingsViewModel.username.value == "" ||
this.composingMessage.value == "",
);
this.searchViewModel = new SearchViewModel(
this.chatMessageViewModels,
this.filteredMessageViewModels,
(chatMessageViewModel) => [chatMessageViewModel.body.value],
new React.ListState(),
);
}
}