add inline replies, ui improvements, rename ViewPersistence->ViewController, add scroll method and highlight

This commit is contained in:
marlon-erler
2026-04-14 13:15:38 +00:00
parent 634e898317
commit f4a3450b14
19 changed files with 508 additions and 122 deletions
+2 -2
View File
@@ -13,7 +13,7 @@ import { TaskSettingsModal } from "../Modals/taskSettingsModal";
import { TaskViewModelToEntry } from "../Components/taskEntry";
import { setFocusWithDelay } from "../utility";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { ViewPersistence } from "../viewPersistence";
import { ViewController } from "../viewController";
export function BoardPage(
coreViewModel: CoreViewModel,
@@ -23,7 +23,7 @@ export function BoardPage(
// main content
const persistenceId = boardViewModel.boardInfo.fileId;
const pages = ViewPersistence.boardPages.setPages(persistenceId, () =>
const pages = ViewController.boardPages.setItems(persistenceId, () =>
React.createProxyState([boardViewModel.selectedPage], () => {
switch (boardViewModel.selectedPage.value) {
case BoardPageTypes.Kanban: {
+67 -9
View File
@@ -1,11 +1,21 @@
/* layout */
#chat-page #main #message-page .content {
padding: 0px;
overflow: hidden;
display: grid;
grid-template-rows: 1fr var(--control-height) var(--safe-area-bottom);
--composer-height: var(--control-height);
grid-template-rows:
1fr calc(var(--composer-height) + var(--gap-between-tiles))
var(--safe-area-bottom);
}
#chat-page
#main
#message-page
.content:has(.reply-preview-wrapper .reply-preview) {
--composer-height: calc(
2 * var(--control-height) + var(--gap-between-tiles)
);
}
#message-page #message-container {
@@ -20,21 +30,51 @@
#message-page #composer input {
margin: 0px;
width: 100%;
max-width: unset;
flex: 1;
border-top: 1px solid var(--border);
border-left: 1px solid var(--border);
}
#message-page #composer .content-width-constraint {
display: flex;
align-items: flex-end;
justify-content: center;
flex-direction: column;
gap: var(--gap-between-tiles);
}
#message-page #composer .reply-preview-wrapper {
display: flex;
justify-content: flex-end;
width: 100%;
}
#message-page #composer .reply-preview-wrapper .reply-preview {
width: 100%;
max-width: var(--max-input-width);
display: flex;
gap: var(--gap-between-tiles);
}
#message-page #composer .reply-preview-wrapper .reply-preview > div {
background: var(--surface);
display: flex;
align-items: center;
gap: var(--text-gap);
padding: 0px var(--content-padding);
width: calc(100% - var(--control-height) - var(--gap-between-tiles));
}
@media (max-width: 700px) {
#message-page #composer div {
width: 100%;
max-width: unset;
display: flex;
}
}
@@ -44,7 +84,6 @@
#message-page #composer .input-width-constraint {
display: flex;
justify-content: flex-end;
width: 100%;
max-width: var(--max-content-width);
}
@@ -178,12 +217,31 @@
text-align: right;
}
.message-bubble > .inline-reply {
cursor: pointer;
display: flex;
align-items: center;
background: var(--surface-alt);
height: var(--control-height);
max-width: var(--max-input-width);
width: 100%;
overflow: hidden;
padding: 0px var(--control-padding);
gap: var(--text-gap);
border-left: var(--outline-width) solid var(--primary);
}
.message-bubble > .message-reaction-row {
max-width: var(--max-input-width);
width: 100%;
padding: var(--gap-between-tiles);
background: var(--surface);
background: var(--surface-alt);
display: none !important;
overflow: hidden;
+26
View File
@@ -8,6 +8,8 @@ import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
import { ChatMessage } from "../Components/chatMessage";
import { MessageFilterModal } from "../Modals/messageFilterModal";
import { setFocusWithDelay } from "../utility";
import { ViewController } from "../viewController";
import { ReplyPreview } from "../Components/replyPreview";
export function MessagePage(
coreViewModel: CoreViewModel,
@@ -31,6 +33,23 @@ export function MessagePage(
></div>
);
const persistenceId = messagePageViewModel.chatViewModel.chatModel.id;
const replyPreview = ViewController.inlineReplies.setItems(
persistenceId,
() =>
React.createProxyState(
[messagePageViewModel.replyingMessage],
() => {
if (messagePageViewModel.replyingMessage.value == undefined)
return <div></div>;
return ReplyPreview(
coreViewModel,
messagePageViewModel.replyingMessage.value,
);
},
),
);
function scrollDown(hard: boolean = false) {
if (hard) {
messageContainer.setAttribute("scroll-hard", "");
@@ -51,6 +70,9 @@ export function MessagePage(
);
setTimeout(() => scrollDown(true), 100);
messagePageViewModel.replyingMessage.subscribeSilent(() => {
setFocusWithDelay();
})
setFocusWithDelay();
return (
@@ -84,6 +106,10 @@ export function MessagePage(
{messageContainer}
<div id="composer">
<div class="content-width-constraint">
<div
class="reply-preview-wrapper"
children:set={replyPreview}
></div>
<div class="input-width-constraint">
<input
id="focused"
+2 -2
View File
@@ -8,7 +8,7 @@ import TaskPageViewModel from "../../ViewModel/Pages/taskPageViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { PlaceholderView } from "../Components/placeholderView";
import { v4 } from "uuid";
import { ViewPersistence } from "../viewPersistence";
import { ViewController } from "../viewController";
export function TaskPage(
coreViewModel: CoreViewModel,
@@ -22,7 +22,7 @@ export function TaskPage(
);
const persistenceId = taskPageViewModel.chatViewModel.chatModel.id;
const pages = ViewPersistence.taskPages.setPages(persistenceId, () =>
const pages = ViewController.taskPages.setItems(persistenceId, () =>
React.createProxyState([taskPageViewModel.selectedBoardId], () => {
const selectedBoardId = taskPageViewModel.selectedBoardId.value;
if (selectedBoardId == undefined) {