improve keystrokes, cleanup
This commit is contained in:
Vendored
+1
-1
@@ -597,7 +597,7 @@ body[showing-chat] #chat-page-wrapper {
|
||||
padding-bottom: calc(var(--message-container-padding) + var(--content-padding)) !important;
|
||||
}
|
||||
#chat-page #main #message-page .content:has(.reply-preview-wrapper .reply-preview) #message-container {
|
||||
--message-container-padding: calc(2 * var(--control-height) + var(--gap-between-tiles));
|
||||
--message-container-padding: calc( 2 * var(--control-height) + var(--gap-between-tiles) );
|
||||
}
|
||||
#message-page #message-container {
|
||||
overflow: auto;
|
||||
|
||||
Vendored
+157
-118
@@ -2378,26 +2378,84 @@
|
||||
}
|
||||
};
|
||||
|
||||
// src/View/utility.ts
|
||||
function allowDrop(event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
function allowDrag(event) {
|
||||
event.dataTransfer?.setData("text", "");
|
||||
}
|
||||
function reload() {
|
||||
window.location.reload();
|
||||
}
|
||||
function setFocus() {
|
||||
const focusedInModal = document.querySelector(
|
||||
".modal[open] #focused"
|
||||
);
|
||||
if (focusedInModal) return focusedInModal.focus();
|
||||
document.getElementById("focused")?.focus();
|
||||
}
|
||||
function setFocusWithDelay() {
|
||||
setTimeout(setFocus, 100);
|
||||
}
|
||||
// src/View/viewController.ts
|
||||
var Tracker = class {
|
||||
};
|
||||
var TrackerMap = class {
|
||||
constructor() {
|
||||
this.trackers = /* @__PURE__ */ new Map();
|
||||
this.register = (key) => {
|
||||
if (this.trackers.has(key)) {
|
||||
return this.trackers.get(key);
|
||||
}
|
||||
const tracker = new Tracker();
|
||||
this.trackers.set(key, tracker);
|
||||
return tracker;
|
||||
};
|
||||
this.setState = (key, stateBuilder) => {
|
||||
const tracker = this.register(key);
|
||||
if (tracker.state != void 0) {
|
||||
return tracker.state;
|
||||
} else {
|
||||
tracker.state = stateBuilder();
|
||||
return tracker.state;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
var ViewController = class {
|
||||
static {
|
||||
this.chatPages = new Tracker();
|
||||
}
|
||||
static {
|
||||
this.taskPages = new TrackerMap();
|
||||
}
|
||||
static {
|
||||
this.boardPages = new TrackerMap();
|
||||
}
|
||||
static {
|
||||
this.inlineReplies = new TrackerMap();
|
||||
}
|
||||
static {
|
||||
this.scrollToView = (id) => {
|
||||
const element = document.getElementById(id);
|
||||
if (!element) return;
|
||||
element.scrollIntoView();
|
||||
element.setAttribute("scrolled", "");
|
||||
setTimeout(() => element.removeAttribute("scrolled"), 1e3);
|
||||
};
|
||||
}
|
||||
static {
|
||||
this.allowDrop = (event) => {
|
||||
event.preventDefault();
|
||||
};
|
||||
}
|
||||
static {
|
||||
this.allowDrag = (event) => {
|
||||
event.dataTransfer?.setData("text", "");
|
||||
};
|
||||
}
|
||||
static {
|
||||
this.reload = () => {
|
||||
window.location.reload();
|
||||
};
|
||||
}
|
||||
static {
|
||||
this.setFocus = () => {
|
||||
const focusedInModal = document.querySelector(
|
||||
".modal[open] #focused"
|
||||
);
|
||||
if (focusedInModal) return focusedInModal.focus();
|
||||
document.getElementById("focused")?.focus();
|
||||
};
|
||||
}
|
||||
static {
|
||||
this.setFocusWithDelay = () => {
|
||||
console.trace("focus");
|
||||
setTimeout(this.setFocus, 100);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// src/ViewModel/Pages/taskViewModel.ts
|
||||
var TaskViewModel = class extends Context {
|
||||
@@ -2427,7 +2485,7 @@
|
||||
this.versionIds = new ListState();
|
||||
// methods
|
||||
this.dragStart = (event) => {
|
||||
allowDrag(event);
|
||||
ViewController.allowDrag(event);
|
||||
this.coreViewModel.draggedObject.value = this;
|
||||
};
|
||||
this.setCategoryAndStatus = (category, status) => {
|
||||
@@ -2842,12 +2900,12 @@
|
||||
this.messagePageViewModel.decryptMessage(this);
|
||||
};
|
||||
this.reply = () => {
|
||||
this.messagePageViewModel.replyingMessage.value = this;
|
||||
this.messagePageViewModel.setReply(this);
|
||||
this.hideInfoModal();
|
||||
};
|
||||
this.cancelReply = () => {
|
||||
if (this.messagePageViewModel.replyingMessage.value != this) return;
|
||||
this.messagePageViewModel.replyingMessage.value = void 0;
|
||||
this.messagePageViewModel.setReply(void 0);
|
||||
};
|
||||
// view
|
||||
this.showInfoModal = () => {
|
||||
@@ -2882,7 +2940,9 @@
|
||||
this.body.value = this.chatMessage.body;
|
||||
this.status.value = this.chatMessage.status;
|
||||
if (this.chatMessage.inlineReplyId) {
|
||||
this.inlineReply = this.messagePageViewModel.chatMessageViewModels.value.get(this.chatMessage.inlineReplyId);
|
||||
this.inlineReply = this.messagePageViewModel.chatMessageViewModels.value.get(
|
||||
this.chatMessage.inlineReplyId
|
||||
);
|
||||
}
|
||||
};
|
||||
this.chatMessage = chatMessage;
|
||||
@@ -2994,6 +3054,7 @@
|
||||
void 0
|
||||
);
|
||||
this.composingMessage = new State("");
|
||||
this.focusSetter = new State(null);
|
||||
// methods
|
||||
this.sendMessage = () => {
|
||||
if (this.cannotSendMessage.value == true) return;
|
||||
@@ -3005,10 +3066,7 @@
|
||||
if (this.replyingMessage.value) {
|
||||
replyId = this.replyingMessage.value.chatMessage.id;
|
||||
}
|
||||
this.chatViewModel.chatModel.sendMessage(
|
||||
body,
|
||||
replyId
|
||||
);
|
||||
this.chatViewModel.chatModel.sendMessage(body, replyId);
|
||||
this.replyingMessage.value = void 0;
|
||||
};
|
||||
this.decryptMessage = async (messageViewModel) => {
|
||||
@@ -3024,6 +3082,14 @@
|
||||
isDeleting
|
||||
);
|
||||
};
|
||||
this.setReply = (chatMessageViewModel) => {
|
||||
this.replyingMessage.value = chatMessageViewModel;
|
||||
this.setFocus();
|
||||
};
|
||||
this.resetReply = () => {
|
||||
this.replyingMessage.value = void 0;
|
||||
this.setFocus();
|
||||
};
|
||||
// view
|
||||
this.showChatMessage = (chatMessage) => {
|
||||
const chatMessageViewModel = new ChatMessageViewModel(
|
||||
@@ -3064,6 +3130,9 @@
|
||||
this.revokeReactionFilter();
|
||||
this.searchViewModel.search("");
|
||||
};
|
||||
this.setFocus = () => {
|
||||
this.focusSetter.callSubscriptions();
|
||||
};
|
||||
// load
|
||||
this.loadData = () => {
|
||||
this.chatMessageViewModels.clear();
|
||||
@@ -3092,8 +3161,15 @@
|
||||
() => this.searchViewModel.appliedQuery.value != "" || this.reactionFilter.value != void 0
|
||||
);
|
||||
this.registerKeyStroke("=" /* Filter */, this.showFilterModal);
|
||||
this.registerKeyStroke("backspace" /* CloseOrCancel */, this.hideFilterModal);
|
||||
this.registerKeyStroke("backspace" /* CloseOrCancel */, () => {
|
||||
if (this.isFilterModalOpen.value == true) {
|
||||
this.hideFilterModal();
|
||||
} else {
|
||||
this.replyingMessage.value = void 0;
|
||||
}
|
||||
});
|
||||
this.registerKeyStroke("-" /* Reset */, this.resetFilter);
|
||||
this.registerKeyStroke(";" /* Create */, this.setFocus);
|
||||
this.chatViewModel.registerContext("messages" /* Messages */, this);
|
||||
}
|
||||
};
|
||||
@@ -3526,7 +3602,8 @@
|
||||
this.closeCurrentContext();
|
||||
};
|
||||
this.handleBoardClosed = (boardViewModel) => {
|
||||
if (boardViewModel.boardInfo.fileId != this.selectedBoardId.value) return;
|
||||
if (boardViewModel.boardInfo.fileId != this.selectedBoardId.value)
|
||||
return;
|
||||
this.selectedBoardId.value = void 0;
|
||||
this.chatViewModel.resetColor();
|
||||
};
|
||||
@@ -3945,7 +4022,7 @@
|
||||
"on:click": select,
|
||||
"toggle:selected": isSelected,
|
||||
"toggle:today": isToday,
|
||||
"on:dragover": allowDrop,
|
||||
"on:dragover": ViewController.allowDrop,
|
||||
"on:drop": drop
|
||||
},
|
||||
/* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("b", null, date), /* @__PURE__ */ createElement(
|
||||
@@ -4255,7 +4332,7 @@
|
||||
if (calendarPageViewModel.selectedTaskViewModel.value == void 0) {
|
||||
return /* @__PURE__ */ createElement("div", null);
|
||||
} else {
|
||||
setFocusWithDelay();
|
||||
ViewController.setFocusWithDelay();
|
||||
return TaskSettingsModal(
|
||||
coreViewModel2,
|
||||
calendarPageViewModel.selectedTaskViewModel.value
|
||||
@@ -4510,56 +4587,6 @@
|
||||
);
|
||||
}
|
||||
|
||||
// src/View/viewController.ts
|
||||
var ItemTracker = class {
|
||||
};
|
||||
var ViewTrackerMap = class {
|
||||
constructor() {
|
||||
this.trackers = /* @__PURE__ */ new Map();
|
||||
this.register = (key) => {
|
||||
if (this.trackers.has(key)) {
|
||||
return this.trackers.get(key);
|
||||
}
|
||||
const tracker = new ItemTracker();
|
||||
this.trackers.set(key, tracker);
|
||||
return tracker;
|
||||
};
|
||||
this.setItems = (key, views) => {
|
||||
const tracker = this.register(key);
|
||||
if (tracker.items != void 0) {
|
||||
return tracker.items;
|
||||
} else {
|
||||
tracker.items = views();
|
||||
return tracker.items;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
var ViewController = class {
|
||||
static {
|
||||
this.chatPages = new ItemTracker();
|
||||
}
|
||||
static {
|
||||
this.taskPages = new ViewTrackerMap();
|
||||
}
|
||||
static {
|
||||
this.boardPages = new ViewTrackerMap();
|
||||
}
|
||||
static {
|
||||
this.inlineReplies = new ViewTrackerMap();
|
||||
}
|
||||
static {
|
||||
this.messageIcons = new ViewTrackerMap();
|
||||
}
|
||||
static scrollToView(id) {
|
||||
const element = document.getElementById(id);
|
||||
if (!element) return;
|
||||
element.scrollIntoView();
|
||||
element.setAttribute("scrolled", "");
|
||||
setTimeout(() => element.removeAttribute("scrolled"), 1e3);
|
||||
}
|
||||
};
|
||||
|
||||
// src/View/Components/inlineReply.tsx
|
||||
function InlineReply(chatMessageViewModel) {
|
||||
const reply = chatMessageViewModel.inlineReply;
|
||||
@@ -4572,22 +4599,18 @@
|
||||
|
||||
// src/View/Components/chatMessage.tsx
|
||||
function ChatMessage4(coreViewModel2, chatMessageViewModel) {
|
||||
const persistenceId = chatMessageViewModel.chatMessage.id;
|
||||
const statusIcon = ViewController.messageIcons.setItems(persistenceId, () => createProxyState(
|
||||
[chatMessageViewModel.status],
|
||||
() => {
|
||||
switch (chatMessageViewModel.status.value) {
|
||||
case "outbox" /* Outbox */:
|
||||
return "hourglass_top";
|
||||
case "sent" /* Sent */:
|
||||
return "check";
|
||||
case "received" /* Received */:
|
||||
return "done_all";
|
||||
default:
|
||||
return "warning";
|
||||
}
|
||||
const statusIcon = createProxyState([chatMessageViewModel.status], () => {
|
||||
switch (chatMessageViewModel.status.value) {
|
||||
case "outbox" /* Outbox */:
|
||||
return "hourglass_top";
|
||||
case "sent" /* Sent */:
|
||||
return "check";
|
||||
case "received" /* Received */:
|
||||
return "done_all";
|
||||
default:
|
||||
return "warning";
|
||||
}
|
||||
));
|
||||
});
|
||||
return /* @__PURE__ */ createElement(
|
||||
"div",
|
||||
{
|
||||
@@ -4656,7 +4679,18 @@
|
||||
[messagePageViewModel.reactionFilter],
|
||||
() => messagePageViewModel.reactionFilter.value == void 0
|
||||
);
|
||||
messagePageViewModel.isFilterModalOpen.subscribe(setFocusWithDelay);
|
||||
messagePageViewModel.isFilterModalOpen.subscribe((isOpen) => {
|
||||
if (isOpen == false) return;
|
||||
ViewController.setFocusWithDelay();
|
||||
});
|
||||
createProxyState(
|
||||
[messagePageViewModel.isFilterModalOpen],
|
||||
() => {
|
||||
if (messagePageViewModel.isFilterModalOpen.value == false)
|
||||
return;
|
||||
ViewController.setFocusWithDelay();
|
||||
}
|
||||
);
|
||||
return /* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": messagePageViewModel.isFilterModalOpen }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, coreViewModel2.translations.chatPage.message.messageFilterHeadline), /* @__PURE__ */ createElement("div", { class: "flex-row width-input" }, /* @__PURE__ */ createElement(
|
||||
"input",
|
||||
{
|
||||
@@ -4704,7 +4738,13 @@
|
||||
|
||||
// src/View/Components/replyPreview.tsx
|
||||
function ReplyPreview(coreViewModel2, chatMessageViewModel) {
|
||||
return /* @__PURE__ */ createElement("div", { class: "reply-preview" }, /* @__PURE__ */ createElement("div", { class: "surface blur" }, /* @__PURE__ */ createElement("span", { class: "secondary" }, chatMessageViewModel.sender), /* @__PURE__ */ createElement("b", { class: "ellipsis", "subscribe:innerText": chatMessageViewModel.body })), /* @__PURE__ */ createElement(
|
||||
return /* @__PURE__ */ createElement("div", { class: "reply-preview" }, /* @__PURE__ */ createElement("div", { class: "surface blur" }, /* @__PURE__ */ createElement("span", { class: "secondary" }, chatMessageViewModel.sender), /* @__PURE__ */ createElement(
|
||||
"b",
|
||||
{
|
||||
class: "ellipsis",
|
||||
"subscribe:innerText": chatMessageViewModel.body
|
||||
}
|
||||
)), /* @__PURE__ */ createElement(
|
||||
"button",
|
||||
{
|
||||
class: "standard square blur",
|
||||
@@ -4732,7 +4772,7 @@
|
||||
}
|
||||
);
|
||||
const persistenceId = messagePageViewModel.chatViewModel.chatModel.id;
|
||||
const replyPreview = ViewController.inlineReplies.setItems(
|
||||
const replyPreview = ViewController.inlineReplies.setState(
|
||||
persistenceId,
|
||||
() => createProxyState(
|
||||
[messagePageViewModel.replyingMessage],
|
||||
@@ -4762,10 +4802,9 @@
|
||||
scrollDownIfApplicable
|
||||
);
|
||||
setTimeout(() => scrollDown(true), 100);
|
||||
messagePageViewModel.replyingMessage.subscribeSilent(() => {
|
||||
setFocusWithDelay();
|
||||
messagePageViewModel.focusSetter.subscribeSilent(() => {
|
||||
ViewController.setFocusWithDelay();
|
||||
});
|
||||
setFocusWithDelay();
|
||||
return /* @__PURE__ */ createElement("div", { id: "message-page" }, /* @__PURE__ */ createElement("div", { class: "pane-wrapper" }, /* @__PURE__ */ createElement("div", { class: "pane" }, /* @__PURE__ */ createElement("div", { class: "toolbar" }, /* @__PURE__ */ createElement("span", { class: "title" }, coreViewModel2.translations.chatPage.message.messagesHeadline), /* @__PURE__ */ createElement("span", null, /* @__PURE__ */ createElement(
|
||||
"button",
|
||||
{
|
||||
@@ -5081,7 +5120,7 @@
|
||||
"div",
|
||||
{
|
||||
class: "flex-column flex-no",
|
||||
"on:dragover": allowDrop,
|
||||
"on:dragover": ViewController.allowDrop,
|
||||
"on:drop": drop
|
||||
},
|
||||
/* @__PURE__ */ createElement("div", { class: "flex-row width-input" }, /* @__PURE__ */ createElement(
|
||||
@@ -5119,7 +5158,7 @@
|
||||
|
||||
// src/View/Modals/boardSettingsModal.tsx
|
||||
function BoardSettingsModal(coreViewModel2, boardViewModel) {
|
||||
boardViewModel.isPresentingSettingsModal.subscribe(setFocusWithDelay);
|
||||
boardViewModel.isPresentingSettingsModal.subscribe(ViewController.setFocusWithDelay);
|
||||
return /* @__PURE__ */ createElement(
|
||||
"div",
|
||||
{
|
||||
@@ -5302,7 +5341,7 @@
|
||||
"div",
|
||||
{
|
||||
class: "status-column gap",
|
||||
"on:dragover": allowDrop,
|
||||
"on:dragover": ViewController.allowDrop,
|
||||
"on:drop": drop,
|
||||
"children:append": [taskViewModels, TaskViewModelToEntry]
|
||||
}
|
||||
@@ -5331,7 +5370,10 @@
|
||||
isOpen.value = false;
|
||||
}
|
||||
const suggestionId = v4_default();
|
||||
isOpen.subscribe(setFocusWithDelay);
|
||||
isOpen.subscribe((isOpen2) => {
|
||||
if (!isOpen2) return;
|
||||
ViewController.setFocusWithDelay();
|
||||
});
|
||||
return /* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": isOpen, extended: true }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, headline), /* @__PURE__ */ createElement("div", { class: "flex-row width-input" }, /* @__PURE__ */ createElement(
|
||||
"input",
|
||||
{
|
||||
@@ -5377,7 +5419,7 @@
|
||||
function BoardPage(coreViewModel2, boardViewModel) {
|
||||
boardViewModel.loadData();
|
||||
const persistenceId = boardViewModel.boardInfo.fileId;
|
||||
const pages = ViewController.boardPages.setItems(
|
||||
const pages = ViewController.boardPages.setState(
|
||||
persistenceId,
|
||||
() => createProxyState([boardViewModel.selectedPage], () => {
|
||||
switch (boardViewModel.selectedPage.value) {
|
||||
@@ -5408,7 +5450,7 @@
|
||||
if (boardViewModel.selectedTaskViewModel.value == void 0) {
|
||||
return /* @__PURE__ */ createElement("div", null);
|
||||
} else {
|
||||
setFocusWithDelay();
|
||||
ViewController.setFocusWithDelay();
|
||||
return TaskSettingsModal(
|
||||
coreViewModel2,
|
||||
boardViewModel.selectedTaskViewModel.value
|
||||
@@ -5491,7 +5533,7 @@
|
||||
class: "tile colored-tile",
|
||||
"toggle:selected": boardViewModel.isSelected,
|
||||
"on:click": boardViewModel.select,
|
||||
"on:dragover": allowDrop,
|
||||
"on:dragover": ViewController.allowDrop,
|
||||
"on:drop": boardViewModel.handleDropBetweenBoards
|
||||
},
|
||||
/* @__PURE__ */ createElement(
|
||||
@@ -5520,7 +5562,7 @@
|
||||
() => taskPageViewModel.selectedBoardId.value != void 0
|
||||
);
|
||||
const persistenceId = taskPageViewModel.chatViewModel.chatModel.id;
|
||||
const pages = ViewController.taskPages.setItems(
|
||||
const pages = ViewController.taskPages.setState(
|
||||
persistenceId,
|
||||
() => createProxyState([taskPageViewModel.selectedBoardId], () => {
|
||||
const selectedBoardId = taskPageViewModel.selectedBoardId.value;
|
||||
@@ -5592,7 +5634,7 @@
|
||||
|
||||
// src/View/chatPage.tsx
|
||||
function ChatPage(coreViewModel2, chatViewModel) {
|
||||
ViewController.chatPages.items = createProxyState(
|
||||
ViewController.chatPages.state = createProxyState(
|
||||
[chatViewModel.selectedPage],
|
||||
() => {
|
||||
switch (chatViewModel.selectedPage.value) {
|
||||
@@ -5687,7 +5729,7 @@
|
||||
"div",
|
||||
{
|
||||
id: "main",
|
||||
"children:set": ViewController.chatPages.items
|
||||
"children:set": ViewController.chatPages.state
|
||||
}
|
||||
))
|
||||
);
|
||||
@@ -6541,7 +6583,7 @@
|
||||
StringToTextSpan
|
||||
]
|
||||
}
|
||||
)), /* @__PURE__ */ createElement("button", { "on:click": reload }, coreViewModel2.translations.general.reloadAppButton, /* @__PURE__ */ createElement("span", { class: "icon" }, "refresh"))));
|
||||
)), /* @__PURE__ */ createElement("button", { "on:click": ViewController.reload }, coreViewModel2.translations.general.reloadAppButton, /* @__PURE__ */ createElement("span", { class: "icon" }, "refresh"))));
|
||||
}
|
||||
|
||||
// src/Model/Global/fileTransferModel.ts
|
||||
@@ -6954,10 +6996,7 @@
|
||||
"change",
|
||||
() => this.applyTheme()
|
||||
);
|
||||
this.registerKeyStroke(
|
||||
"backspace" /* CloseOrCancel */,
|
||||
this.close
|
||||
);
|
||||
this.registerKeyStroke("backspace" /* CloseOrCancel */, this.close);
|
||||
}
|
||||
static generateThemeMedia() {
|
||||
return window.matchMedia("(prefers-color-scheme: dark)");
|
||||
|
||||
@@ -10,8 +10,8 @@ import { FilteredList } from "../Components/filteredList";
|
||||
import { TaskCategoryBulkChangeViewModel } from "../../ViewModel/Utility/taskPropertyBulkChangeViewModel";
|
||||
import TaskViewModel from "../../ViewModel/Pages/taskViewModel";
|
||||
import { TaskViewModelToEntry } from "../Components/taskEntry";
|
||||
import { allowDrop } from "../utility";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
import { ViewController } from "../viewController";
|
||||
|
||||
export function BoardKanbanPage(
|
||||
coreViewModel: CoreViewModel,
|
||||
@@ -75,7 +75,7 @@ function Column(
|
||||
const view = (
|
||||
<div
|
||||
class="flex-column flex-no"
|
||||
on:dragover={allowDrop}
|
||||
on:dragover={ViewController.allowDrop}
|
||||
on:drop={drop}
|
||||
>
|
||||
<div class="flex-row width-input">
|
||||
|
||||
@@ -11,7 +11,6 @@ import { BoardViewToggleButton } from "../Components/boardViewToggleButton";
|
||||
import { SearchModal } from "../Modals/searchModal";
|
||||
import { TaskSettingsModal } from "../Modals/taskSettingsModal";
|
||||
import { TaskViewModelToEntry } from "../Components/taskEntry";
|
||||
import { setFocusWithDelay } from "../utility";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
import { ViewController } from "../viewController";
|
||||
|
||||
@@ -23,7 +22,7 @@ export function BoardPage(
|
||||
|
||||
// main content
|
||||
const persistenceId = boardViewModel.boardInfo.fileId;
|
||||
const pages = ViewController.boardPages.setItems(persistenceId, () =>
|
||||
const pages = ViewController.boardPages.setState(persistenceId, () =>
|
||||
React.createProxyState([boardViewModel.selectedPage], () => {
|
||||
switch (boardViewModel.selectedPage.value) {
|
||||
case BoardPageTypes.Kanban: {
|
||||
@@ -54,7 +53,7 @@ export function BoardPage(
|
||||
if (boardViewModel.selectedTaskViewModel.value == undefined) {
|
||||
return <div></div>;
|
||||
} else {
|
||||
setFocusWithDelay();
|
||||
ViewController.setFocusWithDelay();
|
||||
|
||||
return TaskSettingsModal(
|
||||
coreViewModel,
|
||||
|
||||
@@ -15,8 +15,8 @@ import BoardViewModel from "../../ViewModel/Pages/boardViewModel";
|
||||
import { FilteredList } from "../Components/filteredList";
|
||||
import TaskViewModel from "../../ViewModel/Pages/taskViewModel";
|
||||
import { TaskViewModelToEntry } from "../Components/taskEntry";
|
||||
import { allowDrop } from "../utility";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
import { ViewController } from "../viewController";
|
||||
|
||||
export function BoardStatusGridPage(
|
||||
coreViewModel: CoreViewModel,
|
||||
@@ -246,7 +246,7 @@ function StatusColumn(
|
||||
const view = (
|
||||
<div
|
||||
class="status-column gap"
|
||||
on:dragover={allowDrop}
|
||||
on:dragover={ViewController.allowDrop}
|
||||
on:drop={drop}
|
||||
children:append={[taskViewModels, TaskViewModelToEntry]}
|
||||
></div>
|
||||
|
||||
@@ -2,14 +2,13 @@ import "./calendarPage.css";
|
||||
|
||||
import * as React from "bloatless-react";
|
||||
|
||||
import CalendarModel from "../../Model/Files/calendarModel";
|
||||
import CalendarPageViewModel from "../../ViewModel/Pages/calendarPageViewModel";
|
||||
import { MonthGrid } from "../Components/monthGrid";
|
||||
import { TaskSettingsModal } from "../Modals/taskSettingsModal";
|
||||
import { TaskViewModelToEntry } from "../Components/taskEntry";
|
||||
import { setFocusWithDelay } from "../utility";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
import { PlaceholderView } from "../Components/placeholderView";
|
||||
import { ViewController } from "../viewController";
|
||||
|
||||
export function CalendarPage(
|
||||
coreViewModel: CoreViewModel,
|
||||
@@ -95,7 +94,7 @@ export function CalendarPage(
|
||||
) {
|
||||
return <div></div>;
|
||||
} else {
|
||||
setFocusWithDelay();
|
||||
ViewController.setFocusWithDelay();
|
||||
|
||||
return TaskSettingsModal(
|
||||
coreViewModel,
|
||||
|
||||
@@ -9,11 +9,19 @@
|
||||
|
||||
#chat-page #main #message-page .content #message-container {
|
||||
--message-container-padding: var(--control-height);
|
||||
padding-bottom: calc(var(--message-container-padding) + var(--content-padding)) !important;
|
||||
padding-bottom: calc(
|
||||
var(--message-container-padding) + var(--content-padding)
|
||||
) !important;
|
||||
}
|
||||
|
||||
#chat-page #main #message-page .content:has(.reply-preview-wrapper .reply-preview) #message-container {
|
||||
--message-container-padding: calc(2 * var(--control-height) + var(--gap-between-tiles));
|
||||
#chat-page
|
||||
#main
|
||||
#message-page
|
||||
.content:has(.reply-preview-wrapper .reply-preview)
|
||||
#message-container {
|
||||
--message-container-padding: calc(
|
||||
2 * var(--control-height) + var(--gap-between-tiles)
|
||||
);
|
||||
}
|
||||
|
||||
#message-page #message-container {
|
||||
@@ -62,7 +70,7 @@
|
||||
gap: var(--gap-between-tiles);
|
||||
}
|
||||
|
||||
#message-page #composer .reply-preview-wrapper .reply-preview>div {
|
||||
#message-page #composer .reply-preview-wrapper .reply-preview > div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--text-gap);
|
||||
@@ -81,7 +89,6 @@
|
||||
}
|
||||
|
||||
@media (min-width: 700px) {
|
||||
|
||||
#message-page #composer .content-width-constraint,
|
||||
#message-page #composer .input-width-constraint {
|
||||
display: flex;
|
||||
@@ -227,7 +234,7 @@
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.message-bubble>.inline-reply {
|
||||
.message-bubble > .inline-reply {
|
||||
cursor: pointer;
|
||||
|
||||
display: flex;
|
||||
@@ -246,7 +253,7 @@
|
||||
border-left: var(--outline-width) solid var(--primary);
|
||||
}
|
||||
|
||||
.message-bubble>.message-reaction-row {
|
||||
.message-bubble > .message-reaction-row {
|
||||
max-width: var(--max-input-width);
|
||||
width: 100%;
|
||||
|
||||
@@ -257,11 +264,11 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.message-bubble>.message-reaction-row:has(button:not([count="0"])) {
|
||||
.message-bubble > .message-reaction-row:has(button:not([count="0"])) {
|
||||
display: grid !important;
|
||||
}
|
||||
|
||||
.message-bubble>.message-reaction-row button {
|
||||
.message-bubble > .message-reaction-row button {
|
||||
min-height: unset;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
@@ -271,7 +278,7 @@
|
||||
animation: slide-up var(--animation-duration);
|
||||
}
|
||||
|
||||
.message-bubble>.message-reaction-row button[count="0"] {
|
||||
.message-bubble > .message-reaction-row button[count="0"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -285,7 +292,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.grid.message-reaction-filter {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
@@ -7,7 +7,6 @@ import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
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";
|
||||
|
||||
@@ -34,7 +33,7 @@ export function MessagePage(
|
||||
);
|
||||
|
||||
const persistenceId = messagePageViewModel.chatViewModel.chatModel.id;
|
||||
const replyPreview = ViewController.inlineReplies.setItems(
|
||||
const replyPreview = ViewController.inlineReplies.setState(
|
||||
persistenceId,
|
||||
() =>
|
||||
React.createProxyState(
|
||||
@@ -70,10 +69,9 @@ export function MessagePage(
|
||||
);
|
||||
setTimeout(() => scrollDown(true), 100);
|
||||
|
||||
messagePageViewModel.replyingMessage.subscribeSilent(() => {
|
||||
setFocusWithDelay();
|
||||
})
|
||||
setFocusWithDelay();
|
||||
messagePageViewModel.focusSetter.subscribeSilent(() => {
|
||||
ViewController.setFocusWithDelay();
|
||||
});
|
||||
|
||||
return (
|
||||
<div id="message-page">
|
||||
|
||||
@@ -22,7 +22,7 @@ export function TaskPage(
|
||||
);
|
||||
|
||||
const persistenceId = taskPageViewModel.chatViewModel.chatModel.id;
|
||||
const pages = ViewController.taskPages.setItems(persistenceId, () =>
|
||||
const pages = ViewController.taskPages.setState(persistenceId, () =>
|
||||
React.createProxyState([taskPageViewModel.selectedBoardId], () => {
|
||||
const selectedBoardId = taskPageViewModel.selectedBoardId.value;
|
||||
if (selectedBoardId == undefined) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from "bloatless-react";
|
||||
|
||||
import BoardViewModel from "../../ViewModel/Pages/boardViewModel";
|
||||
import { allowDrop } from "../utility";
|
||||
import { ViewController } from "../viewController";
|
||||
|
||||
export function BoardEntry(boardViewModel: BoardViewModel) {
|
||||
const view = (
|
||||
@@ -10,7 +10,7 @@ export function BoardEntry(boardViewModel: BoardViewModel) {
|
||||
class="tile colored-tile"
|
||||
toggle:selected={boardViewModel.isSelected}
|
||||
on:click={boardViewModel.select}
|
||||
on:dragover={allowDrop}
|
||||
on:dragover={ViewController.allowDrop}
|
||||
on:drop={boardViewModel.handleDropBetweenBoards}
|
||||
>
|
||||
<span
|
||||
|
||||
@@ -12,8 +12,7 @@ export function ChatMessage(
|
||||
coreViewModel: CoreViewModel,
|
||||
chatMessageViewModel: ChatMessageViewModel,
|
||||
) {
|
||||
const persistenceId = chatMessageViewModel.chatMessage.id;
|
||||
const statusIcon = ViewController.messageIcons.setItems(persistenceId, () => React.createProxyState(
|
||||
const statusIcon = React.createProxyState(
|
||||
[chatMessageViewModel.status],
|
||||
() => {
|
||||
switch (chatMessageViewModel.status.value) {
|
||||
@@ -26,8 +25,8 @@ export function ChatMessage(
|
||||
default:
|
||||
return "warning";
|
||||
}
|
||||
}
|
||||
));
|
||||
},
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -4,15 +4,13 @@ import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
import { ViewController } from "../viewController";
|
||||
|
||||
export function InlineReply (
|
||||
chatMessageViewModel: ChatMessageViewModel,
|
||||
) {
|
||||
export function InlineReply(chatMessageViewModel: ChatMessageViewModel) {
|
||||
const reply = chatMessageViewModel.inlineReply;
|
||||
if (reply == undefined) return <div></div>
|
||||
if (reply == undefined) return <div></div>;
|
||||
|
||||
const scroll = () => {
|
||||
ViewController.scrollToView(reply.chatMessage.id);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div class="inline-reply" on:click={scroll}>
|
||||
|
||||
@@ -3,9 +3,9 @@ import "./monthGrid.css";
|
||||
import * as React from "bloatless-react";
|
||||
import { MonthGrid } from "../../Model/Files/calendarModel";
|
||||
import TaskViewModel from "../../ViewModel/Pages/taskViewModel";
|
||||
import { allowDrop } from "../utility";
|
||||
import { localeCompare } from "../../Model/Utility/utility";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
import { ViewController } from "../viewController";
|
||||
|
||||
export function MonthGrid<T>(
|
||||
coreViewModel: CoreViewModel,
|
||||
@@ -93,7 +93,7 @@ export function MonthGrid<T>(
|
||||
on:click={select}
|
||||
toggle:selected={isSelected}
|
||||
toggle:today={isToday}
|
||||
on:dragover={allowDrop}
|
||||
on:dragover={ViewController.allowDrop}
|
||||
on:drop={drop}
|
||||
>
|
||||
<div>
|
||||
|
||||
@@ -11,12 +11,18 @@ export function ReplyPreview(
|
||||
<div class="reply-preview">
|
||||
<div class="surface blur">
|
||||
<span class="secondary">{chatMessageViewModel.sender}</span>
|
||||
<b class="ellipsis" subscribe:innerText={chatMessageViewModel.body}></b>
|
||||
<b
|
||||
class="ellipsis"
|
||||
subscribe:innerText={chatMessageViewModel.body}
|
||||
></b>
|
||||
</div>
|
||||
<button
|
||||
class="standard square blur"
|
||||
on:click={chatMessageViewModel.cancelReply}
|
||||
aria-label={coreViewModel.translations.chatPage.message.cancelReplyAudioLabel}
|
||||
aria-label={
|
||||
coreViewModel.translations.chatPage.message
|
||||
.cancelReplyAudioLabel
|
||||
}
|
||||
>
|
||||
<span class="icon">close</span>
|
||||
</button>
|
||||
|
||||
@@ -4,13 +4,15 @@ import BoardViewModel from "../../ViewModel/Pages/boardViewModel";
|
||||
import { ColorPicker } from "../Components/colorPicker";
|
||||
import { DangerousActionButton } from "../Components/dangerousActionButton";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
import { setFocusWithDelay } from "../utility";
|
||||
import { ViewController } from "../viewController";
|
||||
|
||||
export function BoardSettingsModal(
|
||||
coreViewModel: CoreViewModel,
|
||||
boardViewModel: BoardViewModel,
|
||||
) {
|
||||
boardViewModel.isPresentingSettingsModal.subscribe(setFocusWithDelay);
|
||||
boardViewModel.isPresentingSettingsModal.subscribe(
|
||||
ViewController.setFocusWithDelay,
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -8,8 +8,8 @@ import FileTransferViewModel, {
|
||||
import ConnectionViewModel from "../../ViewModel/Global/connectionViewModel";
|
||||
import StorageModel from "../../Model/Global/storageModel";
|
||||
import { StringToTextSpan } from "../Components/textSpan";
|
||||
import { reload } from "../utility";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
import { ViewController } from "../viewController";
|
||||
|
||||
export function DataTransferModalWrapper(
|
||||
coreViewModel: CoreViewModel,
|
||||
@@ -545,7 +545,7 @@ function DataReceptionModal(
|
||||
]}
|
||||
></div>
|
||||
</main>
|
||||
<button on:click={reload}>
|
||||
<button on:click={ViewController.reload}>
|
||||
{coreViewModel.translations.general.reloadAppButton}
|
||||
<span class="icon">refresh</span>
|
||||
</button>
|
||||
|
||||
@@ -4,7 +4,7 @@ import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
import MessagePageViewModel from "../../ViewModel/Pages/messagePageViewModel";
|
||||
import { MessageReactionFilterButton } from "../Components/messageReactionFilterButton";
|
||||
import { ReactionSymbols } from "../../Model/Chat/chatModel";
|
||||
import { setFocusWithDelay } from "../utility";
|
||||
import { ViewController } from "../viewController";
|
||||
|
||||
export function MessageFilterModal<T>(
|
||||
coreViewModel: CoreViewModel,
|
||||
@@ -16,7 +16,14 @@ export function MessageFilterModal<T>(
|
||||
() => messagePageViewModel.reactionFilter.value == undefined,
|
||||
);
|
||||
|
||||
messagePageViewModel.isFilterModalOpen.subscribe(setFocusWithDelay);
|
||||
messagePageViewModel.isFilterModalOpen.subscribe((isOpen) => {
|
||||
if (isOpen == false) return;
|
||||
ViewController.setFocusWithDelay();
|
||||
});
|
||||
React.createProxyState([messagePageViewModel.isFilterModalOpen], () => {
|
||||
if (messagePageViewModel.isFilterModalOpen.value == false) return;
|
||||
ViewController.setFocusWithDelay();
|
||||
});
|
||||
|
||||
return (
|
||||
<div class="modal" toggle:open={messagePageViewModel.isFilterModalOpen}>
|
||||
|
||||
@@ -4,7 +4,7 @@ import SearchViewModel from "../../ViewModel/Utility/searchViewModel";
|
||||
import { StringToOption } from "../Components/option";
|
||||
import { v4 } from "uuid";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
import { setFocusWithDelay } from "../utility";
|
||||
import { ViewController } from "../viewController";
|
||||
|
||||
export function SearchModal<T>(
|
||||
coreViewModel: CoreViewModel,
|
||||
@@ -19,7 +19,10 @@ export function SearchModal<T>(
|
||||
|
||||
const suggestionId = v4();
|
||||
|
||||
isOpen.subscribe(setFocusWithDelay);
|
||||
isOpen.subscribe((isOpen) => {
|
||||
if (!isOpen) return;
|
||||
ViewController.setFocusWithDelay();
|
||||
});
|
||||
|
||||
return (
|
||||
<div class="modal" toggle:open={isOpen} extended>
|
||||
|
||||
@@ -16,7 +16,7 @@ export function ChatPage(
|
||||
coreViewModel: CoreViewModel,
|
||||
chatViewModel: ChatViewModel,
|
||||
) {
|
||||
ViewController.chatPages.items = React.createProxyState(
|
||||
ViewController.chatPages.state = React.createProxyState(
|
||||
[chatViewModel.selectedPage],
|
||||
() => {
|
||||
switch (chatViewModel.selectedPage.value) {
|
||||
@@ -132,7 +132,7 @@ export function ChatPage(
|
||||
</div>
|
||||
<div
|
||||
id="main"
|
||||
children:set={ViewController.chatPages.items}
|
||||
children:set={ViewController.chatPages.state}
|
||||
></div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
export function allowDrop(event: DragEvent) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
export function allowDrag(event: DragEvent) {
|
||||
event.dataTransfer?.setData("text", "");
|
||||
}
|
||||
|
||||
export function reload() {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
export function setFocus() {
|
||||
const focusedInModal = document.querySelector(
|
||||
".modal[open] #focused",
|
||||
) as HTMLElement;
|
||||
if (focusedInModal) return focusedInModal.focus();
|
||||
document.getElementById("focused")?.focus();
|
||||
}
|
||||
|
||||
export function setFocusWithDelay() {
|
||||
setTimeout(setFocus, 100);
|
||||
}
|
||||
+46
-22
@@ -1,48 +1,72 @@
|
||||
import * as React from "bloatless-react";
|
||||
|
||||
class ItemTracker<T> {
|
||||
items: React.State<T | undefined> | undefined;
|
||||
class Tracker<T> {
|
||||
state: React.State<T> | undefined;
|
||||
}
|
||||
|
||||
class ViewTrackerMap<T> {
|
||||
trackers = new Map<string, ItemTracker<T>>();
|
||||
class TrackerMap<T> {
|
||||
trackers = new Map<string, Tracker<T>>();
|
||||
|
||||
private register = (key: string): ItemTracker<T> => {
|
||||
private register = (key: string): Tracker<T> => {
|
||||
if (this.trackers.has(key)) {
|
||||
return this.trackers.get(key);
|
||||
}
|
||||
const tracker = new ItemTracker<T>();
|
||||
const tracker = new Tracker<T>();
|
||||
this.trackers.set(key, tracker);
|
||||
return tracker;
|
||||
};
|
||||
|
||||
setItems = (
|
||||
setState = (
|
||||
key: string,
|
||||
views: () => React.State<T>,
|
||||
stateBuilder: () => React.State<T>,
|
||||
): React.State<T | undefined> | undefined => {
|
||||
const tracker: ItemTracker<T> = this.register(key);
|
||||
const tracker: Tracker<T> = this.register(key);
|
||||
|
||||
if (tracker.items != undefined) {
|
||||
return tracker.items;
|
||||
if (tracker.state != undefined) {
|
||||
return tracker.state;
|
||||
} else {
|
||||
tracker.items = views();
|
||||
return tracker.items;
|
||||
tracker.state = stateBuilder();
|
||||
return tracker.state;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export class ViewController {
|
||||
static readonly chatPages = new ItemTracker<HTMLElement>();
|
||||
static readonly taskPages = new ViewTrackerMap<HTMLElement>();
|
||||
static readonly boardPages = new ViewTrackerMap<HTMLElement>();
|
||||
static readonly inlineReplies = new ViewTrackerMap<HTMLElement>();
|
||||
static readonly messageIcons = new ViewTrackerMap<string>();
|
||||
static readonly chatPages = new Tracker<HTMLElement>();
|
||||
static readonly taskPages = new TrackerMap<HTMLElement>();
|
||||
static readonly boardPages = new TrackerMap<HTMLElement>();
|
||||
static readonly inlineReplies = new TrackerMap<HTMLElement>();
|
||||
|
||||
static scrollToView(id: string) {
|
||||
static readonly scrollToView = (id: string) => {
|
||||
const element = document.getElementById(id);
|
||||
if (!element) return
|
||||
if (!element) return;
|
||||
element.scrollIntoView();
|
||||
element.setAttribute("scrolled", "");
|
||||
setTimeout(()=>element.removeAttribute("scrolled"), 1000);
|
||||
}
|
||||
setTimeout(() => element.removeAttribute("scrolled"), 1000);
|
||||
};
|
||||
|
||||
static readonly allowDrop = (event: DragEvent) => {
|
||||
event.preventDefault();
|
||||
};
|
||||
|
||||
static readonly allowDrag = (event: DragEvent) => {
|
||||
event.dataTransfer?.setData("text", "");
|
||||
};
|
||||
|
||||
static readonly reload = () => {
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
static readonly setFocus = () => {
|
||||
const focusedInModal = document.querySelector(
|
||||
".modal[open] #focused",
|
||||
) as HTMLElement;
|
||||
if (focusedInModal) return focusedInModal.focus();
|
||||
document.getElementById("focused")?.focus();
|
||||
};
|
||||
|
||||
static readonly setFocusWithDelay = () => {
|
||||
console.trace("focus");
|
||||
setTimeout(this.setFocus, 100);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -82,12 +82,12 @@ export default class ChatMessageViewModel {
|
||||
};
|
||||
|
||||
reply = (): void => {
|
||||
this.messagePageViewModel.replyingMessage.value = this;
|
||||
this.messagePageViewModel.setReply(this);
|
||||
this.hideInfoModal();
|
||||
};
|
||||
cancelReply = (): void => {
|
||||
if (this.messagePageViewModel.replyingMessage.value != this) return;
|
||||
this.messagePageViewModel.replyingMessage.value = undefined;
|
||||
this.messagePageViewModel.setReply(undefined);
|
||||
};
|
||||
|
||||
// view
|
||||
@@ -131,7 +131,10 @@ export default class ChatMessageViewModel {
|
||||
this.status.value = this.chatMessage.status;
|
||||
|
||||
if (this.chatMessage.inlineReplyId) {
|
||||
this.inlineReply = this.messagePageViewModel.chatMessageViewModels.value.get(this.chatMessage.inlineReplyId);
|
||||
this.inlineReply =
|
||||
this.messagePageViewModel.chatMessageViewModels.value.get(
|
||||
this.chatMessage.inlineReplyId,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ export default class ChatViewModel extends ContextHost<ChatPageTypes> {
|
||||
|
||||
handleContextClose = (): void => {
|
||||
this.chatListViewModel.closeChat();
|
||||
}
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(
|
||||
|
||||
@@ -27,7 +27,10 @@ export default class CoreViewModel {
|
||||
history.pushState({ id: context.contextId }, "");
|
||||
}
|
||||
|
||||
closeContext = (contextId: string, fromHistoryEvent: boolean = false): void => {
|
||||
closeContext = (
|
||||
contextId: string,
|
||||
fromHistoryEvent: boolean = false,
|
||||
): void => {
|
||||
if (
|
||||
!this.contexts
|
||||
.map((context) => context.contextId)
|
||||
@@ -81,7 +84,7 @@ export default class CoreViewModel {
|
||||
|
||||
window.onpopstate = () => {
|
||||
this.closeContext(this.context.contextId, true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// util
|
||||
@@ -110,7 +113,7 @@ export class Context {
|
||||
this.keystrokes.set(key, fn);
|
||||
};
|
||||
|
||||
constructor(public contextDebugDescription: string) { }
|
||||
constructor(public contextDebugDescription: string) {}
|
||||
}
|
||||
|
||||
export class ContextHost<T> extends Context {
|
||||
|
||||
@@ -171,7 +171,7 @@ export default class FileTransferViewModel extends Context {
|
||||
|
||||
handleContextClose = (): void => {
|
||||
this.presentedModal.value = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(public readonly coreViewModel: CoreViewModel) {
|
||||
|
||||
@@ -71,7 +71,7 @@ export default class SettingsViewModel extends Context {
|
||||
if (this.requiresReload.value == true) {
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(public readonly coreViewModel: CoreViewModel) {
|
||||
@@ -102,10 +102,7 @@ export default class SettingsViewModel extends Context {
|
||||
);
|
||||
|
||||
// keystrokes
|
||||
this.registerKeyStroke(
|
||||
CommonKeys.CloseOrCancel,
|
||||
this.close,
|
||||
);
|
||||
this.registerKeyStroke(CommonKeys.CloseOrCancel, this.close);
|
||||
}
|
||||
|
||||
static generateThemeMedia(): MediaQueryList {
|
||||
|
||||
@@ -65,7 +65,7 @@ export default class StorageViewModel extends Context {
|
||||
return;
|
||||
}
|
||||
this.isShowingStorageModal.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(public readonly coreViewModel: CoreViewModel) {
|
||||
|
||||
@@ -252,7 +252,7 @@ export default class BoardViewModel extends TaskContainingPageViewModel {
|
||||
|
||||
if (!fromHistoryEvent) return;
|
||||
this.taskPageViewModel.storeLastUsedBoard();
|
||||
}
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(
|
||||
|
||||
@@ -27,6 +27,7 @@ export default class MessagePageViewModel extends Context {
|
||||
undefined,
|
||||
);
|
||||
composingMessage = new React.State<string>("");
|
||||
focusSetter = new React.State(null);
|
||||
|
||||
// guards
|
||||
cannotSendMessage: React.State<boolean>;
|
||||
@@ -40,14 +41,11 @@ export default class MessagePageViewModel extends Context {
|
||||
};
|
||||
|
||||
sendMessageFromBody = (body: string): void => {
|
||||
let replyId: string|undefined = undefined;
|
||||
let replyId: string | undefined = undefined;
|
||||
if (this.replyingMessage.value) {
|
||||
replyId = this.replyingMessage.value.chatMessage.id;
|
||||
}
|
||||
this.chatViewModel.chatModel.sendMessage(
|
||||
body,
|
||||
replyId,
|
||||
);
|
||||
this.chatViewModel.chatModel.sendMessage(body, replyId);
|
||||
this.replyingMessage.value = undefined;
|
||||
};
|
||||
|
||||
@@ -72,6 +70,16 @@ export default class MessagePageViewModel extends Context {
|
||||
);
|
||||
};
|
||||
|
||||
setReply = (chatMessageViewModel: ChatMessageViewModel): void => {
|
||||
this.replyingMessage.value = chatMessageViewModel;
|
||||
this.setFocus();
|
||||
};
|
||||
|
||||
resetReply = (): void => {
|
||||
this.replyingMessage.value = undefined;
|
||||
this.setFocus();
|
||||
};
|
||||
|
||||
// view
|
||||
showChatMessage = (chatMessage: ChatMessage): void => {
|
||||
const chatMessageViewModel = new ChatMessageViewModel(
|
||||
@@ -123,6 +131,10 @@ export default class MessagePageViewModel extends Context {
|
||||
this.searchViewModel.search("");
|
||||
};
|
||||
|
||||
setFocus = (): void => {
|
||||
this.focusSetter.callSubscriptions();
|
||||
};
|
||||
|
||||
// load
|
||||
loadData = (): void => {
|
||||
this.chatMessageViewModels.clear();
|
||||
@@ -168,8 +180,15 @@ export default class MessagePageViewModel extends Context {
|
||||
|
||||
// keystrokes
|
||||
this.registerKeyStroke(CommonKeys.Filter, this.showFilterModal);
|
||||
this.registerKeyStroke(CommonKeys.CloseOrCancel, this.hideFilterModal);
|
||||
this.registerKeyStroke(CommonKeys.CloseOrCancel, () => {
|
||||
if (this.isFilterModalOpen.value == true) {
|
||||
this.hideFilterModal();
|
||||
} else {
|
||||
this.replyingMessage.value = undefined;
|
||||
}
|
||||
});
|
||||
this.registerKeyStroke(CommonKeys.Reset, this.resetFilter);
|
||||
this.registerKeyStroke(CommonKeys.Create, this.setFocus);
|
||||
|
||||
this.chatViewModel.registerContext(ChatPageTypes.Messages, this);
|
||||
}
|
||||
|
||||
@@ -114,10 +114,11 @@ export default class TaskPageViewModel extends ContextHost<string> {
|
||||
|
||||
closeBoard = (): void => {
|
||||
this.closeCurrentContext();
|
||||
}
|
||||
};
|
||||
|
||||
handleBoardClosed = (boardViewModel: BoardViewModel): void => {
|
||||
if (boardViewModel.boardInfo.fileId != this.selectedBoardId.value) return;
|
||||
if (boardViewModel.boardInfo.fileId != this.selectedBoardId.value)
|
||||
return;
|
||||
|
||||
this.selectedBoardId.value = undefined;
|
||||
this.chatViewModel.resetColor();
|
||||
|
||||
@@ -8,9 +8,8 @@ import { localeCompare, padZero } from "../../Model/Utility/utility";
|
||||
import ChatViewModel from "../Chat/chatViewModel";
|
||||
import CoreViewModel, { Context } from "../Global/coreViewModel";
|
||||
import TaskContainingPageViewModel from "./taskContainingPageViewModel";
|
||||
import { allowDrag } from "../../View/utility";
|
||||
import { v4 } from "uuid";
|
||||
import { CommonKeys } from "../../View/keystrokes";
|
||||
import { ViewController } from "../../View/viewController";
|
||||
|
||||
export default class TaskViewModel extends Context {
|
||||
// util
|
||||
@@ -63,7 +62,7 @@ export default class TaskViewModel extends Context {
|
||||
|
||||
// methods
|
||||
dragStart = (event: DragEvent): void => {
|
||||
allowDrag(event);
|
||||
ViewController.allowDrag(event);
|
||||
this.coreViewModel.draggedObject.value = this;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user