format
This commit is contained in:
+19
-10
@@ -97,8 +97,11 @@ export default class ChatModel {
|
|||||||
};
|
};
|
||||||
|
|
||||||
readonly getPreviousFilterPath = (): string[] => {
|
readonly getPreviousFilterPath = (): string[] => {
|
||||||
return [StorageModelSubPaths.Chat, ...filePaths.chat.previousFilter(this.id)];
|
return [
|
||||||
}
|
StorageModelSubPaths.Chat,
|
||||||
|
...filePaths.chat.previousFilter(this.id),
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
// handlers
|
// handlers
|
||||||
readonly handleMessage = (body: string): void => {
|
readonly handleMessage = (body: string): void => {
|
||||||
@@ -264,15 +267,15 @@ export default class ChatModel {
|
|||||||
|
|
||||||
readonly syncInfo = (): void => {
|
readonly syncInfo = (): void => {
|
||||||
this.sendMessage("", undefined, this.info);
|
this.sendMessage("", undefined, this.info);
|
||||||
}
|
};
|
||||||
|
|
||||||
readonly storeFilter = (filter: string): void => {
|
readonly storeFilter = (filter: string): void => {
|
||||||
this.storageModel.write(this.getPreviousFilterPath(), filter);
|
this.storageModel.write(this.getPreviousFilterPath(), filter);
|
||||||
}
|
};
|
||||||
|
|
||||||
readonly getFilter = (): string => {
|
readonly getFilter = (): string => {
|
||||||
return this.storageModel.read(this.getPreviousFilterPath()) || "";
|
return this.storageModel.read(this.getPreviousFilterPath()) || "";
|
||||||
}
|
};
|
||||||
|
|
||||||
readonly delete = () => {
|
readonly delete = () => {
|
||||||
// untrack
|
// untrack
|
||||||
@@ -285,11 +288,13 @@ export default class ChatModel {
|
|||||||
|
|
||||||
// load
|
// load
|
||||||
readonly loadInfo = (): void => {
|
readonly loadInfo = (): void => {
|
||||||
let info: ChatInfoFileContent | null = this.storageModel.readStringifiable(
|
let info: ChatInfoFileContent | null =
|
||||||
|
this.storageModel.readStringifiable(
|
||||||
this.getInfoPath(),
|
this.getInfoPath(),
|
||||||
ChatInfoReference,
|
ChatInfoReference,
|
||||||
);
|
);
|
||||||
this.info = (info || ChatModel.generateChatInfo("0", "0", Colors.Standard));
|
this.info =
|
||||||
|
info || ChatModel.generateChatInfo("0", "0", Colors.Standard);
|
||||||
this.storeInfo();
|
this.storeInfo();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -297,7 +302,7 @@ export default class ChatModel {
|
|||||||
this.info = info;
|
this.info = info;
|
||||||
this.changeHandlerManager.trigger(null);
|
this.changeHandlerManager.trigger(null);
|
||||||
this.storeInfo();
|
this.storeInfo();
|
||||||
}
|
};
|
||||||
|
|
||||||
get messages(): ChatMessage[] {
|
get messages(): ChatMessage[] {
|
||||||
const messageIds: string[] = this.storageModel.list(
|
const messageIds: string[] = this.storageModel.list(
|
||||||
@@ -373,7 +378,11 @@ export default class ChatModel {
|
|||||||
return channelString.split("/");
|
return channelString.split("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
static generateChatInfo = (name: string, id: string, color: Colors): ChatInfoFileContent => {
|
static generateChatInfo = (
|
||||||
|
name: string,
|
||||||
|
id: string,
|
||||||
|
color: Colors,
|
||||||
|
): ChatInfoFileContent => {
|
||||||
const file = FileModel.createFileContent(id, "chat-info");
|
const file = FileModel.createFileContent(id, "chat-info");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -552,4 +561,4 @@ export const ChatMessageReactionReference: ChatMessageReaction = {
|
|||||||
content: "",
|
content: "",
|
||||||
|
|
||||||
isDeleting: false,
|
isDeleting: false,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
import FileModel, { FileModelSubPath } from "./fileModel";
|
import FileModel, { FileModelSubPath } from "./fileModel";
|
||||||
import { TaskFileContent } from "./boardsAndTasksModel";
|
import { TaskFileContent } from "./boardsAndTasksModel";
|
||||||
|
import { isoToMonthString, padZero } from "../Utility/utility";
|
||||||
import StorageModel from "../Global/storageModel";
|
import StorageModel from "../Global/storageModel";
|
||||||
import SettingsModel from "../Global/settingsModel";
|
import SettingsModel from "../Global/settingsModel";
|
||||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||||
import {isoToMonthString, padZero} from "../Utility/utility";
|
|
||||||
|
|
||||||
export default class CalendarModel {
|
export default class CalendarModel {
|
||||||
readonly storageModel: StorageModel;
|
readonly storageModel: StorageModel;
|
||||||
@@ -35,9 +35,7 @@ export default class CalendarModel {
|
|||||||
readonly storeTaskReference = (taskFileContent: TaskFileContent): void => {
|
readonly storeTaskReference = (taskFileContent: TaskFileContent): void => {
|
||||||
if (taskFileContent.date == undefined) return;
|
if (taskFileContent.date == undefined) return;
|
||||||
|
|
||||||
const monthString: string = isoToMonthString(
|
const monthString: string = isoToMonthString(taskFileContent.date);
|
||||||
taskFileContent.date,
|
|
||||||
);
|
|
||||||
|
|
||||||
const monthPath: string[] = this.getMonthPath(monthString);
|
const monthPath: string[] = this.getMonthPath(monthString);
|
||||||
const referencePath: string[] = [...monthPath, taskFileContent.fileId];
|
const referencePath: string[] = [...monthPath, taskFileContent.fileId];
|
||||||
@@ -103,9 +101,7 @@ export default class CalendarModel {
|
|||||||
};
|
};
|
||||||
|
|
||||||
for (let i = 0; i < daysInMonth; i++) {
|
for (let i = 0; i < daysInMonth; i++) {
|
||||||
const paddedDate: string = padZero(
|
const paddedDate: string = padZero((i + 1).toString(), 2);
|
||||||
(i + 1).toString(), 2
|
|
||||||
);
|
|
||||||
grid.days[paddedDate] = defaultValueCreator();
|
grid.days[paddedDate] = defaultValueCreator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,13 +8,21 @@ import {
|
|||||||
parseValidObject,
|
parseValidObject,
|
||||||
stringify,
|
stringify,
|
||||||
} from "../Utility/utility";
|
} from "../Utility/utility";
|
||||||
import { checkIsValidObject, checkMatchesObjectStructure, DATA_VERSION, ValidObject } from "../Utility/typeSafety";
|
import {
|
||||||
|
checkIsValidObject,
|
||||||
|
checkMatchesObjectStructure,
|
||||||
|
DATA_VERSION,
|
||||||
|
ValidObject,
|
||||||
|
} from "../Utility/typeSafety";
|
||||||
import StorageModel, {
|
import StorageModel, {
|
||||||
StorageModelSubPaths,
|
StorageModelSubPaths,
|
||||||
filePaths,
|
filePaths,
|
||||||
} from "../Global/storageModel";
|
} from "../Global/storageModel";
|
||||||
import SettingsModel from "../Global/settingsModel";
|
import SettingsModel from "../Global/settingsModel";
|
||||||
import ChatModel, {ChatInfoFileContent, ChatInfoReference} from "../Chat/chatModel";
|
import ChatModel, {
|
||||||
|
ChatInfoFileContent,
|
||||||
|
ChatInfoReference,
|
||||||
|
} from "../Chat/chatModel";
|
||||||
|
|
||||||
export default class FileModel {
|
export default class FileModel {
|
||||||
readonly storageModel: StorageModel;
|
readonly storageModel: StorageModel;
|
||||||
@@ -70,7 +78,11 @@ export default class FileModel {
|
|||||||
console.log(fileContent.type);
|
console.log(fileContent.type);
|
||||||
|
|
||||||
if (fileContent.type == "chat-info") {
|
if (fileContent.type == "chat-info") {
|
||||||
if (checkMatchesObjectStructure(fileContent, ChatInfoReference) == false) return;
|
if (
|
||||||
|
checkMatchesObjectStructure(fileContent, ChatInfoReference) ==
|
||||||
|
false
|
||||||
|
)
|
||||||
|
return;
|
||||||
this.chatModel.handleInfo(fileContent as ChatInfoFileContent);
|
this.chatModel.handleInfo(fileContent as ChatInfoFileContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
|
import {
|
||||||
import { bytesToMB, localeCompare, parseValidObject, stringify } from "../Utility/utility";
|
bytesToMB,
|
||||||
|
localeCompare,
|
||||||
|
parseValidObject,
|
||||||
|
stringify,
|
||||||
|
} from "../Utility/utility";
|
||||||
import { DATA_VERSION, ValidObject } from "../Utility/typeSafety";
|
import { DATA_VERSION, ValidObject } from "../Utility/typeSafety";
|
||||||
|
|
||||||
export const PATH_COMPONENT_SEPARATOR = "\\";
|
export const PATH_COMPONENT_SEPARATOR = "\\";
|
||||||
@@ -171,7 +175,7 @@ export default class StorageModel {
|
|||||||
return capacity;
|
return capacity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
readonly calculateUsage = (): number => {
|
readonly calculateUsage = (): number => {
|
||||||
let data = JSON.stringify(localStorage);
|
let data = JSON.stringify(localStorage);
|
||||||
@@ -181,7 +185,7 @@ export default class StorageModel {
|
|||||||
const mb = bytesToMB(bytes);
|
const mb = bytesToMB(bytes);
|
||||||
const rounded = Math.round(mb * 100) / 100;
|
const rounded = Math.round(mb * 100) / 100;
|
||||||
return rounded;
|
return rounded;
|
||||||
}
|
};
|
||||||
|
|
||||||
// tree
|
// tree
|
||||||
readonly initializeTree = (): void => {
|
readonly initializeTree = (): void => {
|
||||||
@@ -285,7 +289,10 @@ export const filePaths = {
|
|||||||
...filePaths.chat.chatBase(id),
|
...filePaths.chat.chatBase(id),
|
||||||
"reactions",
|
"reactions",
|
||||||
],
|
],
|
||||||
previousFilter: (id: string) => [...filePaths.chat.chatBase(id), "previous-filter"],
|
previousFilter: (id: string) => [
|
||||||
|
...filePaths.chat.chatBase(id),
|
||||||
|
"previous-filter",
|
||||||
|
],
|
||||||
lastUsedPage: (id: string) => [
|
lastUsedPage: (id: string) => [
|
||||||
...filePaths.chat.chatBase(id),
|
...filePaths.chat.chatBase(id),
|
||||||
"last-used-page",
|
"last-used-page",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { checkIsValidObject, checkMatchesObjectStructure } from "./typeSafety";
|
import { checkIsValidObject, checkMatchesObjectStructure } from "./typeSafety";
|
||||||
|
import CalendarModel from "../Files/calendarModel";
|
||||||
import * as React from "../../react";
|
import * as React from "../../react";
|
||||||
import { CalendarPage } from "../../View/ChatPages/calendarPage";
|
import { CalendarPage } from "../../View/ChatPages/calendarPage";
|
||||||
import CalendarModel from "../Files/calendarModel";
|
|
||||||
|
|
||||||
export interface Stringifiable {
|
export interface Stringifiable {
|
||||||
toString(): string;
|
toString(): string;
|
||||||
@@ -24,32 +24,43 @@ export function isoToDateString (dateISOString: string): string {
|
|||||||
const [year, month, date] = dateISOString.split("-");
|
const [year, month, date] = dateISOString.split("-");
|
||||||
const paddedDate = padZero(date ?? "", 2);
|
const paddedDate = padZero(date ?? "", 2);
|
||||||
return paddedDate;
|
return paddedDate;
|
||||||
};
|
}
|
||||||
|
|
||||||
export function isoToMonthString(dateISOString: string): string {
|
export function isoToMonthString(dateISOString: string): string {
|
||||||
const [year, month, _] = dateISOString.split("-");
|
const [year, month, _] = dateISOString.split("-");
|
||||||
return formatMonthStringFromParts(year, month);
|
return formatMonthStringFromParts(year, month);
|
||||||
};
|
|
||||||
|
|
||||||
export function formatISO(date: Date): string {
|
|
||||||
return formatISOFromParts(date.getFullYear(), date.getMonth()+1, date.getDate())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatISOFromParts(year: number|string, month: number|string, date: number|string): string {
|
export function formatISO(date: Date): string {
|
||||||
|
return formatISOFromParts(
|
||||||
|
date.getFullYear(),
|
||||||
|
date.getMonth() + 1,
|
||||||
|
date.getDate(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatISOFromParts(
|
||||||
|
year: number | string,
|
||||||
|
month: number | string,
|
||||||
|
date: number | string,
|
||||||
|
): string {
|
||||||
return [year, month, date]
|
return [year, month, date]
|
||||||
.map((x, i) => i == 0 ? x : padZero(x.toString(), 2))
|
.map((x, i) => (i == 0 ? x : padZero(x.toString(), 2)))
|
||||||
.join("-");
|
.join("-");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatMonthStringFromParts (year: string = "", month: string = ""): string {
|
export function formatMonthStringFromParts(
|
||||||
|
year: string = "",
|
||||||
|
month: string = "",
|
||||||
|
): string {
|
||||||
const paddedYear: string = padZero(year, 4);
|
const paddedYear: string = padZero(year, 4);
|
||||||
const paddedMonth: string = padZero(month, 2);
|
const paddedMonth: string = padZero(month, 2);
|
||||||
return `${paddedYear}-${paddedMonth}`;
|
return `${paddedYear}-${paddedMonth}`;
|
||||||
};
|
}
|
||||||
|
|
||||||
export function formatTime(date: Date): string {
|
export function formatTime(date: Date): string {
|
||||||
return [date.getHours(), date.getMinutes()]
|
return [date.getHours(), date.getMinutes()]
|
||||||
.map(x => padZero(x.toString(), 2))
|
.map((x) => padZero(x.toString(), 2))
|
||||||
.join(":");
|
.join(":");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,7 +152,12 @@ export default function implementFilter<T>(
|
|||||||
function update() {
|
function update() {
|
||||||
matches.clear();
|
matches.clear();
|
||||||
allItems.value.forEach((item: T) => {
|
allItems.value.forEach((item: T) => {
|
||||||
if (!itemToString(item).toLowerCase().includes(query.value.toLowerCase())) return;
|
if (
|
||||||
|
!itemToString(item)
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(query.value.toLowerCase())
|
||||||
|
)
|
||||||
|
return;
|
||||||
matches.add(item);
|
matches.add(item);
|
||||||
allItems.handleRemoval(item, () => {
|
allItems.handleRemoval(item, () => {
|
||||||
matches.remove(item);
|
matches.remove(item);
|
||||||
@@ -271,7 +287,10 @@ export interface PinchToZoomData {
|
|||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
}
|
}
|
||||||
export function implementPinchZoom(canvas: HTMLElement, data: React.State<PinchToZoomData>) {
|
export function implementPinchZoom(
|
||||||
|
canvas: HTMLElement,
|
||||||
|
data: React.State<PinchToZoomData>,
|
||||||
|
) {
|
||||||
let pinching = false;
|
let pinching = false;
|
||||||
let dragging = false;
|
let dragging = false;
|
||||||
let lastElement: HTMLElement | undefined = undefined;
|
let lastElement: HTMLElement | undefined = undefined;
|
||||||
@@ -318,15 +337,17 @@ export function implementPinchZoom(canvas: HTMLElement, data: React.State<PinchT
|
|||||||
if (_offset) [x, y] = _offset;
|
if (_offset) [x, y] = _offset;
|
||||||
|
|
||||||
data.value = {
|
data.value = {
|
||||||
zoom, x, y
|
zoom,
|
||||||
}
|
x,
|
||||||
|
y,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
data.subscribe((data) => {
|
data.subscribe((data) => {
|
||||||
const el = element();
|
const el = element();
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
el.style.transform = `scale(${data.zoom.toString()}) translate(${data.x}px, ${data.y}px)`;
|
el.style.transform = `scale(${data.zoom.toString()}) translate(${data.x}px, ${data.y}px)`;
|
||||||
})
|
});
|
||||||
|
|
||||||
canvas.addEventListener("wheel", (event: WheelEvent) => {
|
canvas.addEventListener("wheel", (event: WheelEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@@ -352,20 +373,18 @@ export function implementPinchZoom(canvas: HTMLElement, data: React.State<PinchT
|
|||||||
initialTouchX = event.clientX;
|
initialTouchX = event.clientX;
|
||||||
initialTouchY = event.clientY;
|
initialTouchY = event.clientY;
|
||||||
dragging = true;
|
dragging = true;
|
||||||
})
|
});
|
||||||
canvas.addEventListener("mouseup", () => {
|
canvas.addEventListener("mouseup", () => {
|
||||||
dragging = false;
|
dragging = false;
|
||||||
})
|
});
|
||||||
canvas.addEventListener("mousemove", (event: MouseEvent) => {
|
canvas.addEventListener("mousemove", (event: MouseEvent) => {
|
||||||
if (!dragging) return;
|
if (!dragging) return;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
apply(data.value.zoom, [
|
apply(data.value.zoom, [
|
||||||
initialX +
|
initialX + (event.clientX - initialTouchX) / initialZoom,
|
||||||
(event.clientX - initialTouchX) / initialZoom,
|
initialY + (event.clientY - initialTouchY) / initialZoom,
|
||||||
initialY +
|
|
||||||
(event.clientY - initialTouchY) / initialZoom,
|
|
||||||
]);
|
]);
|
||||||
})
|
});
|
||||||
|
|
||||||
canvas.addEventListener("touchstart", (event: TouchEvent) => {
|
canvas.addEventListener("touchstart", (event: TouchEvent) => {
|
||||||
(document.activeElement as HTMLElement)?.blur();
|
(document.activeElement as HTMLElement)?.blur();
|
||||||
|
|||||||
@@ -46,7 +46,10 @@ export function BoardPage(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const wrapper = (
|
const wrapper = (
|
||||||
<div class="content main-content allow-drag-move" children:set={pages}></div>
|
<div
|
||||||
|
class="content main-content allow-drag-move"
|
||||||
|
children:set={pages}
|
||||||
|
></div>
|
||||||
);
|
);
|
||||||
Utility.implementPinchZoom(wrapper, boardViewModel.pinchToZoomData);
|
Utility.implementPinchZoom(wrapper, boardViewModel.pinchToZoomData);
|
||||||
|
|
||||||
|
|||||||
@@ -285,7 +285,8 @@
|
|||||||
padding: var(--gap-between-tiles);
|
padding: var(--gap-between-tiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
#message-page[reply-view] :is(.reply-link, .inline-reply, #composer .reply-preview-wrapper) {
|
#message-page[reply-view]
|
||||||
|
:is(.reply-link, .inline-reply, #composer .reply-preview-wrapper) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,20 +65,40 @@ function scrollDownIfApplicable() {
|
|||||||
messagePageViewModel.filteredMessageViewModels.subscribeSilent(
|
messagePageViewModel.filteredMessageViewModels.subscribeSilent(
|
||||||
scrollDownIfApplicable,
|
scrollDownIfApplicable,
|
||||||
);
|
);
|
||||||
React.bulkSubscribe([messagePageViewModel.reactionFilter, messagePageViewModel.searchViewModel.appliedQuery], scrollDown)
|
React.bulkSubscribe(
|
||||||
messagePageViewModel.replyViewSelectedMessage.subscribeSilent(selectedMessage => {
|
[
|
||||||
|
messagePageViewModel.reactionFilter,
|
||||||
|
messagePageViewModel.searchViewModel.appliedQuery,
|
||||||
|
],
|
||||||
|
scrollDown,
|
||||||
|
);
|
||||||
|
messagePageViewModel.replyViewSelectedMessage.subscribeSilent(
|
||||||
|
(selectedMessage) => {
|
||||||
if (selectedMessage != undefined) return;
|
if (selectedMessage != undefined) return;
|
||||||
setTimeout(scrollDown, 100);
|
setTimeout(scrollDown, 100);
|
||||||
})
|
},
|
||||||
|
);
|
||||||
setTimeout(() => scrollDown(true), 100);
|
setTimeout(() => scrollDown(true), 100);
|
||||||
|
|
||||||
messagePageViewModel.focusSetter.subscribeSilent(() => {
|
messagePageViewModel.focusSetter.subscribeSilent(() => {
|
||||||
ViewController.setFocusWithDelay();
|
ViewController.setFocusWithDelay();
|
||||||
});
|
});
|
||||||
|
|
||||||
const isInReplyView = React.createProxyState([messagePageViewModel.replyViewSelectedMessage], ()=>messagePageViewModel.replyViewSelectedMessage.value != undefined);
|
const isInReplyView = React.createProxyState(
|
||||||
|
[messagePageViewModel.replyViewSelectedMessage],
|
||||||
|
() => messagePageViewModel.replyViewSelectedMessage.value != undefined,
|
||||||
|
);
|
||||||
|
|
||||||
const title = React.createProxyState([messagePageViewModel.isReplyViewActive], ()=>messagePageViewModel.isReplyViewActive.value ? coreViewModel.translations.chatPage.message.replyHeaderLabel((messagePageViewModel.replyViewSelectedMessage.value!).body.value) : coreViewModel.translations.chatPage.message.messagesHeadline);
|
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 (
|
return (
|
||||||
<div id="message-page" toggle:reply-view={isInReplyView}>
|
<div id="message-page" toggle:reply-view={isInReplyView}>
|
||||||
@@ -88,15 +108,16 @@ return (
|
|||||||
<button
|
<button
|
||||||
class="ghost"
|
class="ghost"
|
||||||
on:click={messagePageViewModel.resetReplyView}
|
on:click={messagePageViewModel.resetReplyView}
|
||||||
toggle:hidden={messagePageViewModel.isReplyViewInactive}
|
toggle:hidden={
|
||||||
|
messagePageViewModel.isReplyViewInactive
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<span class="icon">arrow_back</span>
|
<span class="icon">arrow_back</span>
|
||||||
</button>
|
</button>
|
||||||
<span
|
<span
|
||||||
class="title ellipsis width-100 flex"
|
class="title ellipsis width-100 flex"
|
||||||
subscribe:innerText={title}
|
subscribe:innerText={title}
|
||||||
>
|
></span>
|
||||||
</span>
|
|
||||||
<span>
|
<span>
|
||||||
<button
|
<button
|
||||||
class="ghost inset-outline"
|
class="ghost inset-outline"
|
||||||
|
|||||||
@@ -47,12 +47,8 @@ export function SettingsPage(
|
|||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
<input
|
<input
|
||||||
bind:value={
|
bind:value={settingsPageViewModel.nameInput}
|
||||||
settingsPageViewModel.nameInput
|
on:enter={settingsPageViewModel.setName}
|
||||||
}
|
|
||||||
on:enter={
|
|
||||||
settingsPageViewModel.setName
|
|
||||||
}
|
|
||||||
></input>
|
></input>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
@@ -63,9 +59,7 @@ export function SettingsPage(
|
|||||||
coreViewModel.translations.chatPage.settings
|
coreViewModel.translations.chatPage.settings
|
||||||
.setNameButtonAudioLabel
|
.setNameButtonAudioLabel
|
||||||
}
|
}
|
||||||
on:click={
|
on:click={settingsPageViewModel.setName}
|
||||||
settingsPageViewModel.setName
|
|
||||||
}
|
|
||||||
toggle:disabled={
|
toggle:disabled={
|
||||||
settingsPageViewModel.cannotSetPrimaryChannel
|
settingsPageViewModel.cannotSetPrimaryChannel
|
||||||
}
|
}
|
||||||
@@ -186,17 +180,16 @@ export function SettingsPage(
|
|||||||
coreViewModel.translations.chatPage.settings
|
coreViewModel.translations.chatPage.settings
|
||||||
.setColorButtonAudioLabel
|
.setColorButtonAudioLabel
|
||||||
}
|
}
|
||||||
on:click={
|
on:click={settingsPageViewModel.applyColor}
|
||||||
settingsPageViewModel.applyColor
|
toggle:disabled={
|
||||||
|
settingsPageViewModel.cannotSetColor
|
||||||
}
|
}
|
||||||
toggle:disabled={settingsPageViewModel.cannotSetColor}
|
|
||||||
>
|
>
|
||||||
{coreViewModel.translations.general.setButton}
|
{coreViewModel.translations.general.setButton}
|
||||||
<span class="icon">check</span>
|
<span class="icon">check</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<hr></hr>
|
<hr></hr>
|
||||||
|
|
||||||
<div class="width-input">
|
<div class="width-input">
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import "./taskPage.css";
|
|||||||
import { BoardPage } from "./boardPage";
|
import { BoardPage } from "./boardPage";
|
||||||
import { ViewController } from "../viewController";
|
import { ViewController } from "../viewController";
|
||||||
import { PlaceholderView } from "../Components/placeholderView";
|
import { PlaceholderView } from "../Components/placeholderView";
|
||||||
|
import { NewItemEntry } from "../Components/newItemEntry";
|
||||||
import { BoardViewModelToEntry } from "../Components/boardEntry";
|
import { BoardViewModelToEntry } from "../Components/boardEntry";
|
||||||
import * as React from "../../react";
|
import * as React from "../../react";
|
||||||
import TaskPageViewModel from "../../ViewModel/Pages/taskPageViewModel";
|
import TaskPageViewModel from "../../ViewModel/Pages/taskPageViewModel";
|
||||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||||
import {NewItemEntry} from "../Components/newItemEntry";
|
|
||||||
|
|
||||||
export function TaskPage(
|
export function TaskPage(
|
||||||
coreViewModel: CoreViewModel,
|
coreViewModel: CoreViewModel,
|
||||||
@@ -66,13 +66,18 @@ export function TaskPage(
|
|||||||
bind:value={taskPageViewModel.boardQuery}
|
bind:value={taskPageViewModel.boardQuery}
|
||||||
on:enter={taskPageViewModel.createBoard}
|
on:enter={taskPageViewModel.createBoard}
|
||||||
placeholder={
|
placeholder={
|
||||||
coreViewModel.translations.general.filterOrCreateLabel
|
coreViewModel.translations.general
|
||||||
|
.filterOrCreateLabel
|
||||||
}
|
}
|
||||||
></input>
|
></input>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content gap">
|
<div class="content gap">
|
||||||
{NewItemEntry(coreViewModel, taskPageViewModel.boardQuery, taskPageViewModel.createBoard)}
|
{NewItemEntry(
|
||||||
|
coreViewModel,
|
||||||
|
taskPageViewModel.boardQuery,
|
||||||
|
taskPageViewModel.createBoard,
|
||||||
|
)}
|
||||||
<div
|
<div
|
||||||
class="grid gap"
|
class="grid gap"
|
||||||
style="grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr))"
|
style="grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr))"
|
||||||
|
|||||||
@@ -12,14 +12,10 @@ export function ChatEntry(chatViewModel: ChatViewModel) {
|
|||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="shadow"
|
class="shadow"
|
||||||
subscribe:innerText={
|
subscribe:innerText={chatViewModel.settingsPageViewModel.name}
|
||||||
chatViewModel.settingsPageViewModel.name
|
|
||||||
}
|
|
||||||
></span>
|
></span>
|
||||||
<h2
|
<h2
|
||||||
subscribe:innerText={
|
subscribe:innerText={chatViewModel.settingsPageViewModel.name}
|
||||||
chatViewModel.settingsPageViewModel.name
|
|
||||||
}
|
|
||||||
></h2>
|
></h2>
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { ReplyLink } from "./replyLink";
|
||||||
import { MessageReactionButtonRow } from "./messageReactionButtonRow";
|
import { MessageReactionButtonRow } from "./messageReactionButtonRow";
|
||||||
import { InlineReply } from "./inlineReply";
|
import { InlineReply } from "./inlineReply";
|
||||||
import { ChatMessageInfoModal } from "../Modals/chatMessageInfoModal";
|
import { ChatMessageInfoModal } from "../Modals/chatMessageInfoModal";
|
||||||
@@ -5,7 +6,6 @@ import * as React from "../../react";
|
|||||||
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 { ChatMessageStatuses } from "../../Model/Chat/chatModel";
|
import { ChatMessageStatuses } from "../../Model/Chat/chatModel";
|
||||||
import {ReplyLink} from "./replyLink";
|
|
||||||
|
|
||||||
export function ChatMessage(
|
export function ChatMessage(
|
||||||
coreViewModel: CoreViewModel,
|
coreViewModel: CoreViewModel,
|
||||||
@@ -70,7 +70,10 @@ export function ChatMessage(
|
|||||||
coreViewModel.translations.chatPage.message
|
coreViewModel.translations.chatPage.message
|
||||||
.replyToMessageButton
|
.replyToMessageButton
|
||||||
}
|
}
|
||||||
toggle:hidden={chatMessageViewModel.messagePageViewModel.isReplyViewActive}
|
toggle:hidden={
|
||||||
|
chatMessageViewModel.messagePageViewModel
|
||||||
|
.isReplyViewActive
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<span class="icon">reply</span>
|
<span class="icon">reply</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
import * as React from "../../react";
|
import * as React from "../../react";
|
||||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||||
|
|
||||||
export function NewItemEntry(coreViewModel: CoreViewModel, query: React.State<string>, fn: ()=>void) {
|
export function NewItemEntry(
|
||||||
|
coreViewModel: CoreViewModel,
|
||||||
|
query: React.State<string>,
|
||||||
|
fn: () => void,
|
||||||
|
) {
|
||||||
const isHidden = React.createProxyState([query], () => query.value == "");
|
const isHidden = React.createProxyState([query], () => query.value == "");
|
||||||
const label = React.createProxyState([query],()=>coreViewModel.translations.general.createLabel(query.value));
|
const label = React.createProxyState([query], () =>
|
||||||
|
coreViewModel.translations.general.createLabel(query.value),
|
||||||
|
);
|
||||||
|
|
||||||
return <button
|
return (
|
||||||
|
<button
|
||||||
class="standard slide-up"
|
class="standard slide-up"
|
||||||
toggle:hidden={isHidden}
|
toggle:hidden={isHidden}
|
||||||
on:click={fn}
|
on:click={fn}
|
||||||
@@ -13,4 +20,5 @@ export function NewItemEntry(coreViewModel: CoreViewModel, query: React.State<st
|
|||||||
<span subscribe:innerText={label}></span>
|
<span subscribe:innerText={label}></span>
|
||||||
<span class="icon">add</span>
|
<span class="icon">add</span>
|
||||||
</button>
|
</button>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,31 @@
|
|||||||
import * as React from "../../react";
|
import * as React from "../../react";
|
||||||
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
|
|
||||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||||
|
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
|
||||||
|
|
||||||
export function ReplyLink(coreViewModel: CoreViewModel, chatMessageViewModel: ChatMessageViewModel) {
|
export function ReplyLink(
|
||||||
const isHidden = React.createProxyState([chatMessageViewModel.replyCount], ()=>chatMessageViewModel.replyCount.value == 0);
|
coreViewModel: CoreViewModel,
|
||||||
|
chatMessageViewModel: ChatMessageViewModel,
|
||||||
|
) {
|
||||||
|
const isHidden = React.createProxyState(
|
||||||
|
[chatMessageViewModel.replyCount],
|
||||||
|
() => chatMessageViewModel.replyCount.value == 0,
|
||||||
|
);
|
||||||
|
|
||||||
function select() {
|
function select() {
|
||||||
chatMessageViewModel.messagePageViewModel.setReplyView(chatMessageViewModel);
|
chatMessageViewModel.messagePageViewModel.setReplyView(
|
||||||
|
chatMessageViewModel,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div class="reply-link" toggle:hidden={isHidden} on:click={select}>
|
||||||
class="reply-link"
|
<span>
|
||||||
toggle:hidden={isHidden}
|
{coreViewModel.translations.chatPage.message.replyPrefixLabel}
|
||||||
on:click={select}
|
</span>
|
||||||
>
|
<b
|
||||||
<span>{coreViewModel.translations.chatPage.message.replyPrefixLabel}</span>
|
class="ellipsis"
|
||||||
<b class="ellipsis" subscribe:innerText={chatMessageViewModel.replyCount}></b>
|
subscribe:innerText={chatMessageViewModel.replyCount}
|
||||||
|
></b>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,42 @@
|
|||||||
import * as React from "../../react";
|
import * as React from "../../react";
|
||||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
|
||||||
import MessagePageViewModel from "../../ViewModel/Pages/messagePageViewModel";
|
import MessagePageViewModel from "../../ViewModel/Pages/messagePageViewModel";
|
||||||
|
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||||
|
|
||||||
export function ReplyViewHeader(coreViewModel: CoreViewModel, messagePageViewModel: MessagePageViewModel) {
|
export function ReplyViewHeader(
|
||||||
const isHidden = React.createProxyState([messagePageViewModel.isReplyViewActive], ()=>!messagePageViewModel.isReplyViewActive.value);
|
coreViewModel: CoreViewModel,
|
||||||
|
messagePageViewModel: MessagePageViewModel,
|
||||||
|
) {
|
||||||
|
const isHidden = React.createProxyState(
|
||||||
|
[messagePageViewModel.isReplyViewActive],
|
||||||
|
() => !messagePageViewModel.isReplyViewActive.value,
|
||||||
|
);
|
||||||
|
|
||||||
const label = React.createProxyState([messagePageViewModel.replyViewSelectedMessage], ()=>messagePageViewModel.replyViewSelectedMessage.value == undefined ? "" : coreViewModel.translations.chatPage.message.replyHeaderLabel(messagePageViewModel.replyViewSelectedMessage.value.sender));
|
const label = React.createProxyState(
|
||||||
const message = React.createProxyState([messagePageViewModel.replyViewSelectedMessage], ()=>messagePageViewModel.replyViewSelectedMessage.value == undefined ? "" : messagePageViewModel.replyViewSelectedMessage.value.body.value);
|
[messagePageViewModel.replyViewSelectedMessage],
|
||||||
|
() =>
|
||||||
|
messagePageViewModel.replyViewSelectedMessage.value == undefined
|
||||||
|
? ""
|
||||||
|
: coreViewModel.translations.chatPage.message.replyHeaderLabel(
|
||||||
|
messagePageViewModel.replyViewSelectedMessage.value
|
||||||
|
.sender,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const message = React.createProxyState(
|
||||||
|
[messagePageViewModel.replyViewSelectedMessage],
|
||||||
|
() =>
|
||||||
|
messagePageViewModel.replyViewSelectedMessage.value == undefined
|
||||||
|
? ""
|
||||||
|
: messagePageViewModel.replyViewSelectedMessage.value.body
|
||||||
|
.value,
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div class="reply-header" toggle:hidden={isHidden}>
|
||||||
class="reply-header"
|
|
||||||
toggle:hidden={isHidden}
|
|
||||||
>
|
|
||||||
<b class="ellipsis" subscribe:innerText={label}></b>
|
<b class="ellipsis" subscribe:innerText={label}></b>
|
||||||
<span class="secondary ellipsis" subscribe:innerText={message}></span>
|
<span
|
||||||
|
class="secondary ellipsis"
|
||||||
|
subscribe:innerText={message}
|
||||||
|
></span>
|
||||||
<button
|
<button
|
||||||
class="standard square"
|
class="standard square"
|
||||||
on:click={messagePageViewModel.resetReplyView}
|
on:click={messagePageViewModel.resetReplyView}
|
||||||
|
|||||||
@@ -11,9 +11,11 @@ export function TaskEntry(taskViewModel: TaskViewModel) {
|
|||||||
schedule: taskViewModel.time.value || "---",
|
schedule: taskViewModel.time.value || "---",
|
||||||
};
|
};
|
||||||
|
|
||||||
const className = React.createProxyState([taskViewModel.isNotNext], ()=>
|
const className = React.createProxyState(
|
||||||
`${taskViewModel.isNotNext.value ? "standard" : "primary"} tile flex-no`
|
[taskViewModel.isNotNext],
|
||||||
)
|
() =>
|
||||||
|
`${taskViewModel.isNotNext.value ? "standard" : "primary"} tile flex-no`,
|
||||||
|
);
|
||||||
|
|
||||||
const view = (
|
const view = (
|
||||||
<button
|
<button
|
||||||
@@ -24,11 +26,11 @@ export function TaskEntry(taskViewModel: TaskViewModel) {
|
|||||||
on:dragstart={taskViewModel.dragStart}
|
on:dragstart={taskViewModel.dragStart}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<span
|
<span class="secondary" toggle:hidden={taskViewModel.isNotNext}>
|
||||||
class="secondary"
|
{
|
||||||
toggle:hidden={taskViewModel.isNotNext}
|
taskViewModel.coreViewModel.translations.chatPage
|
||||||
>
|
.calendar.eventNext
|
||||||
{taskViewModel.coreViewModel.translations.chatPage.calendar.eventNext}
|
}
|
||||||
<hr></hr>
|
<hr></hr>
|
||||||
</span>
|
</span>
|
||||||
<b
|
<b
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
import * as React from "../../react";
|
import * as React from "../../react";
|
||||||
|
|
||||||
export function UsageBar(label: string, valueLabel: React.State<string>, value: React.State<number>, maximum: React.State<number>) {
|
export function UsageBar(
|
||||||
const style = React.createProxyState([value, maximum], ()=>`width: ${100*(value.value/maximum.value)}%`)
|
label: string,
|
||||||
|
valueLabel: React.State<string>,
|
||||||
|
value: React.State<number>,
|
||||||
|
maximum: React.State<number>,
|
||||||
|
) {
|
||||||
|
const style = React.createProxyState(
|
||||||
|
[value, maximum],
|
||||||
|
() => `width: ${100 * (value.value / maximum.value)}%`,
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div class="surface flex-column padding gap">
|
||||||
class="surface flex-column padding gap"
|
|
||||||
>
|
|
||||||
<b>{label}</b>
|
<b>{label}</b>
|
||||||
<div
|
<div class="width-100 surface-alt" style="height: 18px">
|
||||||
class="width-100 surface-alt"
|
|
||||||
style="height: 18px"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
class="height-100 background-primary"
|
class="height-100 background-primary"
|
||||||
set:style={style}
|
set:style={style}
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span class="secondary" subscribe:innerText={valueLabel}></span>
|
||||||
class="secondary"
|
|
||||||
subscribe:innerText={valueLabel}
|
|
||||||
></span>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,10 @@ export function ChatMessageInfoModal(
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={chatMessageViewModel.reply}
|
on:click={chatMessageViewModel.reply}
|
||||||
toggle:disabled={chatMessageViewModel.messagePageViewModel.isReplyViewActive}
|
toggle:disabled={
|
||||||
|
chatMessageViewModel.messagePageViewModel
|
||||||
|
.isReplyViewActive
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
coreViewModel.translations.chatPage.message
|
coreViewModel.translations.chatPage.message
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { v4 } from "uuid";
|
import { v4 } from "uuid";
|
||||||
import { ViewController } from "../viewController";
|
import { ViewController } from "../viewController";
|
||||||
import { StringToOption } from "../Components/option";
|
import { StringToOption } from "../Components/option";
|
||||||
|
import { DeletableListItem } from "../Components/deletableListItem";
|
||||||
import * as React from "../../react";
|
import * as React from "../../react";
|
||||||
import SearchViewModel from "../../ViewModel/Utility/searchViewModel";
|
import SearchViewModel from "../../ViewModel/Utility/searchViewModel";
|
||||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||||
import {DeletableListItem} from "../Components/deletableListItem";
|
|
||||||
|
|
||||||
export function SearchModal<T>(
|
export function SearchModal<T>(
|
||||||
coreViewModel: CoreViewModel,
|
coreViewModel: CoreViewModel,
|
||||||
@@ -120,7 +120,9 @@ function SuggestionView<T>(
|
|||||||
searchViewModel.search(suggestion);
|
searchViewModel.search(suggestion);
|
||||||
}
|
}
|
||||||
|
|
||||||
return DeletableListItem(coreViewModel, suggestion,
|
return DeletableListItem(
|
||||||
|
coreViewModel,
|
||||||
|
suggestion,
|
||||||
<button
|
<button
|
||||||
class="primary"
|
class="primary"
|
||||||
aria-label={coreViewModel.translations.general.applyButton}
|
aria-label={coreViewModel.translations.general.applyButton}
|
||||||
@@ -128,6 +130,7 @@ function SuggestionView<T>(
|
|||||||
toggle:disabled={isApplied}
|
toggle:disabled={isApplied}
|
||||||
>
|
>
|
||||||
<span class="icon">check</span>
|
<span class="icon">check</span>
|
||||||
</button>
|
</button>,
|
||||||
, deleteSuggestion)
|
deleteSuggestion,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,16 +130,11 @@ function SettingsInfoPane(
|
|||||||
on:click={coreViewModel.update}
|
on:click={coreViewModel.update}
|
||||||
toggle:hidden={coreViewModel.noUpdateAvailable}
|
toggle:hidden={coreViewModel.noUpdateAvailable}
|
||||||
>
|
>
|
||||||
<span
|
<span subscribe:innerText={coreViewModel.updateText}></span>
|
||||||
subscribe:innerText={coreViewModel.updateText}
|
|
||||||
></span>
|
|
||||||
<span class="icon">update</span>
|
<span class="icon">update</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button class="standard" on:click={coreViewModel.checkUpdates}>
|
||||||
class="standard"
|
|
||||||
on:click={coreViewModel.checkUpdates}
|
|
||||||
>
|
|
||||||
{coreViewModel.translations.settings.checkUpdatesButton}
|
{coreViewModel.translations.settings.checkUpdatesButton}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,18 +1,24 @@
|
|||||||
import { SplitModal } from "./splitModal";
|
import { SplitModal } from "./splitModal";
|
||||||
|
import { UsageBar } from "../Components/usageBar";
|
||||||
import { DirectoryItemList } from "../Components/directoryItemList";
|
import { DirectoryItemList } from "../Components/directoryItemList";
|
||||||
import { DangerousActionButton } from "../Components/dangerousActionButton";
|
import { DangerousActionButton } from "../Components/dangerousActionButton";
|
||||||
import * as React from "../../react";
|
import * as React from "../../react";
|
||||||
import StorageViewModel from "../../ViewModel/Global/storageViewModel";
|
import StorageViewModel from "../../ViewModel/Global/storageViewModel";
|
||||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||||
import { PATH_COMPONENT_SEPARATOR } from "../../Model/Global/storageModel";
|
import { PATH_COMPONENT_SEPARATOR } from "../../Model/Global/storageModel";
|
||||||
import {UsageBar} from "../Components/usageBar";
|
|
||||||
|
|
||||||
export function StorageModal(
|
export function StorageModal(
|
||||||
coreViewModel: CoreViewModel,
|
coreViewModel: CoreViewModel,
|
||||||
storageViewModel: StorageViewModel,
|
storageViewModel: StorageViewModel,
|
||||||
) {
|
) {
|
||||||
const usageValueLabel = React.createProxyState([storageViewModel.occupiedSpaceMB, storageViewModel.maximumSpaceMB], ()=>
|
const usageValueLabel = React.createProxyState(
|
||||||
coreViewModel.translations.storage.usageVauleLabel(storageViewModel.occupiedSpaceMB.value, storageViewModel.maximumSpaceMB.value));
|
[storageViewModel.occupiedSpaceMB, storageViewModel.maximumSpaceMB],
|
||||||
|
() =>
|
||||||
|
coreViewModel.translations.storage.usageVauleLabel(
|
||||||
|
storageViewModel.occupiedSpaceMB.value,
|
||||||
|
storageViewModel.maximumSpaceMB.value,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
const detailView = React.createProxyState(
|
const detailView = React.createProxyState(
|
||||||
[storageViewModel.selectedPath],
|
[storageViewModel.selectedPath],
|
||||||
@@ -26,7 +32,12 @@ export function StorageModal(
|
|||||||
|
|
||||||
<hr></hr>
|
<hr></hr>
|
||||||
|
|
||||||
{UsageBar(coreViewModel.translations.storage.usageLabel, usageValueLabel, storageViewModel.occupiedSpaceMB, storageViewModel.maximumSpaceMB)}
|
{UsageBar(
|
||||||
|
coreViewModel.translations.storage.usageLabel,
|
||||||
|
usageValueLabel,
|
||||||
|
storageViewModel.occupiedSpaceMB,
|
||||||
|
storageViewModel.maximumSpaceMB,
|
||||||
|
)}
|
||||||
|
|
||||||
<hr></hr>
|
<hr></hr>
|
||||||
|
|
||||||
|
|||||||
@@ -141,9 +141,7 @@ export function HomePage(
|
|||||||
on:click={coreViewModel.update}
|
on:click={coreViewModel.update}
|
||||||
toggle:hidden={coreViewModel.noUpdateAvailable}
|
toggle:hidden={coreViewModel.noUpdateAvailable}
|
||||||
>
|
>
|
||||||
<span
|
<span subscribe:innerText={coreViewModel.updateText}></span>
|
||||||
subscribe:innerText={coreViewModel.updateText}
|
|
||||||
></span>
|
|
||||||
<span class="icon">update</span>
|
<span class="icon">update</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|||||||
@@ -514,7 +514,8 @@ export const allTranslations: {
|
|||||||
contentEmpty: "(leer)",
|
contentEmpty: "(leer)",
|
||||||
|
|
||||||
usageLabel: "Speicher",
|
usageLabel: "Speicher",
|
||||||
usageVauleLabel: (used: number, max: number) => `${used} von ${max} MB belegt`,
|
usageVauleLabel: (used: number, max: number) =>
|
||||||
|
`${used} von ${max} MB belegt`,
|
||||||
|
|
||||||
path: "Pfad",
|
path: "Pfad",
|
||||||
content: "Inhalt",
|
content: "Inhalt",
|
||||||
@@ -592,7 +593,8 @@ export const allTranslations: {
|
|||||||
questionReaction: "Reaktion: Fragezeichen",
|
questionReaction: "Reaktion: Fragezeichen",
|
||||||
|
|
||||||
replyPrefixLabel: "Antworten: ",
|
replyPrefixLabel: "Antworten: ",
|
||||||
replyHeaderLabel: (message: string) => `Antworten an "${message}"`,
|
replyHeaderLabel: (message: string) =>
|
||||||
|
`Antworten an "${message}"`,
|
||||||
},
|
},
|
||||||
|
|
||||||
task: {
|
task: {
|
||||||
@@ -826,7 +828,8 @@ export const allTranslations: {
|
|||||||
contentEmpty: "(vacío)",
|
contentEmpty: "(vacío)",
|
||||||
|
|
||||||
usageLabel: "Almacenamiento",
|
usageLabel: "Almacenamiento",
|
||||||
usageVauleLabel: (used: number, max: number) => `${used} de ${max} MB en uso`,
|
usageVauleLabel: (used: number, max: number) =>
|
||||||
|
`${used} de ${max} MB en uso`,
|
||||||
|
|
||||||
path: "Ruta",
|
path: "Ruta",
|
||||||
content: "Contenido",
|
content: "Contenido",
|
||||||
@@ -905,7 +908,8 @@ export const allTranslations: {
|
|||||||
questionReaction: "Reaccion: signo de interrogación",
|
questionReaction: "Reaccion: signo de interrogación",
|
||||||
|
|
||||||
replyPrefixLabel: "Respuestas: ",
|
replyPrefixLabel: "Respuestas: ",
|
||||||
replyHeaderLabel: (message: string) => `Respuestas a "${message}"`,
|
replyHeaderLabel: (message: string) =>
|
||||||
|
`Respuestas a "${message}"`,
|
||||||
},
|
},
|
||||||
|
|
||||||
task: {
|
task: {
|
||||||
|
|||||||
@@ -111,5 +111,5 @@ export default class ChatListViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return fullChannel;
|
return fullChannel;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,10 @@ export default class ChatMessageViewModel {
|
|||||||
body: React.State<string> = new React.State("");
|
body: React.State<string> = new React.State("");
|
||||||
inlineReply: ChatMessageViewModel | undefined = undefined;
|
inlineReply: ChatMessageViewModel | undefined = undefined;
|
||||||
replies: React.MapState<ChatMessageViewModel> = new React.MapState();
|
replies: React.MapState<ChatMessageViewModel> = new React.MapState();
|
||||||
replyCount: React.State<number> = React.createProxyState([this.replies], ()=>this.replies.value.size);
|
replyCount: React.State<number> = React.createProxyState(
|
||||||
|
[this.replies],
|
||||||
|
() => this.replies.value.size,
|
||||||
|
);
|
||||||
status: React.State<ChatMessageStatuses | any> = new React.State<any>(
|
status: React.State<ChatMessageStatuses | any> = new React.State<any>(
|
||||||
undefined,
|
undefined,
|
||||||
);
|
);
|
||||||
@@ -139,14 +142,20 @@ export default class ChatMessageViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reply
|
// reply
|
||||||
const selectedMessage = this.messagePageViewModel.replyViewSelectedMessage.value;
|
const selectedMessage =
|
||||||
|
this.messagePageViewModel.replyViewSelectedMessage.value;
|
||||||
if (selectedMessage == undefined) hideForReplyView = false;
|
if (selectedMessage == undefined) hideForReplyView = false;
|
||||||
else if (selectedMessage.chatMessage.id == this.chatMessage.id) hideForReplyView = false;
|
else if (selectedMessage.chatMessage.id == this.chatMessage.id)
|
||||||
else if (this.inlineReply != undefined && selectedMessage.chatMessage.id == this.inlineReply.chatMessage.id) hideForReplyView = false;
|
hideForReplyView = false;
|
||||||
|
else if (
|
||||||
|
this.inlineReply != undefined &&
|
||||||
|
selectedMessage.chatMessage.id == this.inlineReply.chatMessage.id
|
||||||
|
)
|
||||||
|
hideForReplyView = false;
|
||||||
else hideForReplyView = true;
|
else hideForReplyView = true;
|
||||||
|
|
||||||
this.isHidden.value = hideForReactions || hideForReplyView;
|
this.isHidden.value = hideForReactions || hideForReplyView;
|
||||||
}
|
};
|
||||||
|
|
||||||
// reactions
|
// reactions
|
||||||
handleReaction = (reaction: ChatMessageReaction): void => {
|
handleReaction = (reaction: ChatMessageReaction): void => {
|
||||||
@@ -199,7 +208,14 @@ export default class ChatMessageViewModel {
|
|||||||
this.sentByUser = sentByUser;
|
this.sentByUser = sentByUser;
|
||||||
this.loadData();
|
this.loadData();
|
||||||
|
|
||||||
React.bulkSubscribe([this.messagePageViewModel.reactionFilter, this.messagePageViewModel.replyViewSelectedMessage, this.allReactions], this.toggleHiding);
|
React.bulkSubscribe(
|
||||||
|
[
|
||||||
|
this.messagePageViewModel.reactionFilter,
|
||||||
|
this.messagePageViewModel.replyViewSelectedMessage,
|
||||||
|
this.allReactions,
|
||||||
|
],
|
||||||
|
this.toggleHiding,
|
||||||
|
);
|
||||||
this.toggleHiding();
|
this.toggleHiding();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -189,7 +189,10 @@ export default class ChatViewModel extends ContextHost<ChatPageTypes> {
|
|||||||
this.messagePageViewModel.handleReaction(reaction);
|
this.messagePageViewModel.handleReaction(reaction);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
chatModel.changeHandlerManager.setHandler(this.chatModel.id, this.settingsPageViewModel.updateData);
|
chatModel.changeHandlerManager.setHandler(
|
||||||
|
this.chatModel.id,
|
||||||
|
this.settingsPageViewModel.updateData,
|
||||||
|
);
|
||||||
|
|
||||||
// load
|
// load
|
||||||
this.loadPageSelection();
|
this.loadPageSelection();
|
||||||
|
|||||||
@@ -13,9 +13,15 @@ export default class CoreViewModel {
|
|||||||
|
|
||||||
version: React.State<string> = new React.State("");
|
version: React.State<string> = new React.State("");
|
||||||
latestVersion: React.State<string> = new React.State("");
|
latestVersion: React.State<string> = new React.State("");
|
||||||
noUpdateAvailable: React.State<boolean> = React.createProxyState([this.latestVersion], () => {
|
noUpdateAvailable: React.State<boolean> = React.createProxyState(
|
||||||
return (this.latestVersion.value == "" || this.latestVersion.value == this.version.value)
|
[this.latestVersion],
|
||||||
})
|
() => {
|
||||||
|
return (
|
||||||
|
this.latestVersion.value == "" ||
|
||||||
|
this.latestVersion.value == this.version.value
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
updateText: React.State<string> = new React.State("");
|
updateText: React.State<string> = new React.State("");
|
||||||
|
|
||||||
translations: Translations;
|
translations: Translations;
|
||||||
@@ -109,16 +115,19 @@ export default class CoreViewModel {
|
|||||||
console.error(`Could not install service worker: ${error}`);
|
console.error(`Could not install service worker: ${error}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
checkUpdates = (): void => {
|
checkUpdates = (): void => {
|
||||||
fetch("/version").then(async response => {
|
fetch("/version").then(async (response) => {
|
||||||
this.version.value = await response.text();
|
this.version.value = await response.text();
|
||||||
});
|
});
|
||||||
fetch("/latestVersion").then(async response => {
|
fetch("/latestVersion").then(async (response) => {
|
||||||
this.latestVersion.value = (await response.text()).replace("\n", "");
|
this.latestVersion.value = (await response.text()).replace(
|
||||||
})
|
"\n",
|
||||||
}
|
"",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
update = async (): Promise<void> => {
|
update = async (): Promise<void> => {
|
||||||
if (!this.swRegistration) return;
|
if (!this.swRegistration) return;
|
||||||
@@ -126,7 +135,7 @@ export default class CoreViewModel {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
};
|
||||||
|
|
||||||
// init
|
// init
|
||||||
constructor(
|
constructor(
|
||||||
@@ -139,8 +148,9 @@ export default class CoreViewModel {
|
|||||||
this.translations =
|
this.translations =
|
||||||
allTranslations[settingsModel.language] || allTranslations.en;
|
allTranslations[settingsModel.language] || allTranslations.en;
|
||||||
|
|
||||||
this.latestVersion.subscribe(latestVersion => {
|
this.latestVersion.subscribe((latestVersion) => {
|
||||||
this.updateText.value = this.translations.homePage.updateButton(latestVersion);
|
this.updateText.value =
|
||||||
|
this.translations.homePage.updateButton(latestVersion);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.body.addEventListener("keydown", this.handleKeyDown);
|
document.body.addEventListener("keydown", this.handleKeyDown);
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import CoreViewModel, { Context } from "./coreViewModel";
|
import CoreViewModel, { Context } from "./coreViewModel";
|
||||||
import * as React from "../../react";
|
import * as React from "../../react";
|
||||||
import { CommonKeys } from "../../View/keystrokes";
|
import { CommonKeys } from "../../View/keystrokes";
|
||||||
|
import { formatISO } from "../../Model/Utility/utility";
|
||||||
import StorageModel, {
|
import StorageModel, {
|
||||||
StorageModelSubPaths,
|
StorageModelSubPaths,
|
||||||
filePaths,
|
filePaths,
|
||||||
} from "../../Model/Global/storageModel";
|
} from "../../Model/Global/storageModel";
|
||||||
import { TransferData } from "../../Model/Global/fileTransferModel";
|
import { TransferData } from "../../Model/Global/fileTransferModel";
|
||||||
import ChatModel from "../../Model/Chat/chatModel";
|
import ChatModel from "../../Model/Chat/chatModel";
|
||||||
import {formatISO} from "../../Model/Utility/utility";
|
|
||||||
|
|
||||||
export default class FileTransferViewModel extends Context {
|
export default class FileTransferViewModel extends Context {
|
||||||
// state
|
// state
|
||||||
|
|||||||
@@ -16,11 +16,9 @@ export default class NotificationViewModel {
|
|||||||
if (this.seenMessageIds.has(message.id)) return;
|
if (this.seenMessageIds.has(message.id)) return;
|
||||||
if (this.chatListViewModel.selectedChat.value == undefined) return;
|
if (this.chatListViewModel.selectedChat.value == undefined) return;
|
||||||
|
|
||||||
const notification: Notification =
|
const notification: Notification = this.createNotification(message);
|
||||||
this.createNotification(message);
|
|
||||||
const currentChat =
|
const currentChat =
|
||||||
this.chatListViewModel.selectedChat.value.chatModel
|
this.chatListViewModel.selectedChat.value.chatModel.id;
|
||||||
.id;
|
|
||||||
const currentPage =
|
const currentPage =
|
||||||
this.chatListViewModel.selectedChat.value.selectedPage.value;
|
this.chatListViewModel.selectedChat.value.selectedPage.value;
|
||||||
if (
|
if (
|
||||||
@@ -39,10 +37,7 @@ export default class NotificationViewModel {
|
|||||||
|
|
||||||
const chat = [
|
const chat = [
|
||||||
...this.chatListViewModel.chatViewModels.value.values(),
|
...this.chatListViewModel.chatViewModels.value.values(),
|
||||||
].find(
|
].find((chat) => chat.chatModel.id == notification.fullChannel);
|
||||||
(chat) =>
|
|
||||||
chat.chatModel.id == notification.fullChannel,
|
|
||||||
);
|
|
||||||
if (!chat) return;
|
if (!chat) return;
|
||||||
chat.open();
|
chat.open();
|
||||||
chat.openPage(ChatPageTypes.Messages);
|
chat.openPage(ChatPageTypes.Messages);
|
||||||
|
|||||||
@@ -50,9 +50,11 @@ export default class StorageViewModel extends Context {
|
|||||||
};
|
};
|
||||||
|
|
||||||
calculateUsage = (): void => {
|
calculateUsage = (): void => {
|
||||||
this.occupiedSpaceMB.value = this.coreViewModel.storageModel.calculateUsage();
|
this.occupiedSpaceMB.value =
|
||||||
this.maximumSpaceMB.value = this.coreViewModel.storageModel.determineCapacity();
|
this.coreViewModel.storageModel.calculateUsage();
|
||||||
}
|
this.maximumSpaceMB.value =
|
||||||
|
this.coreViewModel.storageModel.determineCapacity();
|
||||||
|
};
|
||||||
|
|
||||||
// view
|
// view
|
||||||
showStorageModal = (): void => {
|
showStorageModal = (): void => {
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import ChatViewModel, { ChatPageTypes } from "../Chat/chatViewModel";
|
|||||||
import * as React from "../../react";
|
import * as React from "../../react";
|
||||||
import { Colors } from "../../colors";
|
import { Colors } from "../../colors";
|
||||||
import { CommonKeys } from "../../View/keystrokes";
|
import { CommonKeys } from "../../View/keystrokes";
|
||||||
|
import { PinchToZoomData } from "../../Model/Utility/utility";
|
||||||
import BoardsAndTasksModel, {
|
import BoardsAndTasksModel, {
|
||||||
BoardInfoFileContent,
|
BoardInfoFileContent,
|
||||||
TaskFileContent,
|
TaskFileContent,
|
||||||
} from "../../Model/Files/boardsAndTasksModel";
|
} from "../../Model/Files/boardsAndTasksModel";
|
||||||
import {PinchToZoomData} from "../../Model/Utility/utility";
|
|
||||||
|
|
||||||
export default class BoardViewModel extends TaskContainingPageViewModel {
|
export default class BoardViewModel extends TaskContainingPageViewModel {
|
||||||
// state
|
// state
|
||||||
@@ -34,7 +34,11 @@ export default class BoardViewModel extends TaskContainingPageViewModel {
|
|||||||
new React.ListState();
|
new React.ListState();
|
||||||
isFilterActive: React.State<boolean>;
|
isFilterActive: React.State<boolean>;
|
||||||
|
|
||||||
pinchToZoomData: React.State<PinchToZoomData> = new React.State({zoom: 1, x: 0, y: 0});
|
pinchToZoomData: React.State<PinchToZoomData> = new React.State({
|
||||||
|
zoom: 1,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
});
|
||||||
|
|
||||||
// paths
|
// paths
|
||||||
getBasePath = (): string[] => {
|
getBasePath = (): string[] => {
|
||||||
|
|||||||
@@ -4,11 +4,19 @@ import CoreViewModel from "../Global/coreViewModel";
|
|||||||
import ChatViewModel, { ChatPageTypes } from "../Chat/chatViewModel";
|
import ChatViewModel, { ChatPageTypes } from "../Chat/chatViewModel";
|
||||||
import * as React from "../../react";
|
import * as React from "../../react";
|
||||||
import { CommonKeys } from "../../View/keystrokes";
|
import { CommonKeys } from "../../View/keystrokes";
|
||||||
|
import {
|
||||||
|
formatISO,
|
||||||
|
formatISOFromParts,
|
||||||
|
formatMonthStringFromParts,
|
||||||
|
formatTime,
|
||||||
|
isoToDateString,
|
||||||
|
isoToMonthString,
|
||||||
|
padZero,
|
||||||
|
} from "../../Model/Utility/utility";
|
||||||
import CalendarModel, { MonthGrid } from "../../Model/Files/calendarModel";
|
import CalendarModel, { MonthGrid } from "../../Model/Files/calendarModel";
|
||||||
import BoardsAndTasksModel, {
|
import BoardsAndTasksModel, {
|
||||||
TaskFileContent,
|
TaskFileContent,
|
||||||
} from "../../Model/Files/boardsAndTasksModel";
|
} from "../../Model/Files/boardsAndTasksModel";
|
||||||
import {formatISO, formatISOFromParts, formatMonthStringFromParts, formatTime, isoToDateString, isoToMonthString, padZero} from "../../Model/Utility/utility";
|
|
||||||
|
|
||||||
export const CALENDAR_EVENT_BOARD_ID = "events";
|
export const CALENDAR_EVENT_BOARD_ID = "events";
|
||||||
|
|
||||||
@@ -22,7 +30,11 @@ export default class CalendarPageViewModel extends TaskContainingPageViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get selectedDateString(): string {
|
get selectedDateString(): string {
|
||||||
return formatISOFromParts(this.selectedYear.value, this.selectedMonth.value, this.selectedDate.value);
|
return formatISOFromParts(
|
||||||
|
this.selectedYear.value,
|
||||||
|
this.selectedMonth.value,
|
||||||
|
this.selectedDate.value,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// paths
|
// paths
|
||||||
@@ -65,9 +77,7 @@ export default class CalendarPageViewModel extends TaskContainingPageViewModel {
|
|||||||
};
|
};
|
||||||
|
|
||||||
getEventsForDate = (): React.MapState<TaskViewModel> | undefined => {
|
getEventsForDate = (): React.MapState<TaskViewModel> | undefined => {
|
||||||
const paddedDate: string = padZero(
|
const paddedDate: string = padZero(this.selectedDate.toString(), 2);
|
||||||
this.selectedDate.toString(), 2
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.monthGrid.value == undefined) {
|
if (this.monthGrid.value == undefined) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@@ -82,9 +92,7 @@ export default class CalendarPageViewModel extends TaskContainingPageViewModel {
|
|||||||
): React.MapState<TaskViewModel> | null => {
|
): React.MapState<TaskViewModel> | null => {
|
||||||
if (this.monthGrid.value == null) return null;
|
if (this.monthGrid.value == null) return null;
|
||||||
|
|
||||||
const date: string = isoToDateString(
|
const date: string = isoToDateString(taskFileContent.date ?? "");
|
||||||
taskFileContent.date ?? "",
|
|
||||||
);
|
|
||||||
return this.monthGrid.value.days[date];
|
return this.monthGrid.value.days[date];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -152,11 +160,7 @@ export default class CalendarPageViewModel extends TaskContainingPageViewModel {
|
|||||||
};
|
};
|
||||||
|
|
||||||
handleDrop = (year: string, month: string, date: string): void => {
|
handleDrop = (year: string, month: string, date: string): void => {
|
||||||
const ISOString: string = formatISOFromParts(
|
const ISOString: string = formatISOFromParts(year, month, date);
|
||||||
year,
|
|
||||||
month,
|
|
||||||
date,
|
|
||||||
);
|
|
||||||
|
|
||||||
const draggedObject: any = this.coreViewModel.draggedObject.value;
|
const draggedObject: any = this.coreViewModel.draggedObject.value;
|
||||||
if (draggedObject instanceof TaskViewModel == false) return;
|
if (draggedObject instanceof TaskViewModel == false) return;
|
||||||
@@ -167,14 +171,11 @@ export default class CalendarPageViewModel extends TaskContainingPageViewModel {
|
|||||||
handleChron = (): void => {
|
handleChron = (): void => {
|
||||||
this.updateMonthGrid();
|
this.updateMonthGrid();
|
||||||
this.updateNextTask();
|
this.updateNextTask();
|
||||||
}
|
};
|
||||||
|
|
||||||
updateMonthGrid = (): void => {
|
updateMonthGrid = (): void => {
|
||||||
const today = formatISO(this.coreViewModel.todayDate.value)
|
const today = formatISO(this.coreViewModel.todayDate.value);
|
||||||
if (
|
if (this.currentTodayDate == today) return;
|
||||||
this.currentTodayDate == today
|
|
||||||
)
|
|
||||||
return;
|
|
||||||
this.loadMonthTasks();
|
this.loadMonthTasks();
|
||||||
this.currentTodayDate = today;
|
this.currentTodayDate = today;
|
||||||
this.selectedDate.callSubscriptions();
|
this.selectedDate.callSubscriptions();
|
||||||
@@ -194,8 +195,8 @@ export default class CalendarPageViewModel extends TaskContainingPageViewModel {
|
|||||||
if (task.time.value <= this.coreViewModel.time.value) continue;
|
if (task.time.value <= this.coreViewModel.time.value) continue;
|
||||||
this.nextTask.value = task;
|
this.nextTask.value = task;
|
||||||
break;
|
break;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// load
|
// load
|
||||||
loadMonthTasks = (): void => {
|
loadMonthTasks = (): void => {
|
||||||
@@ -217,8 +218,7 @@ export default class CalendarPageViewModel extends TaskContainingPageViewModel {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
loadData = (): void => {
|
loadData = (): void => {};
|
||||||
};
|
|
||||||
|
|
||||||
// init
|
// init
|
||||||
constructor(
|
constructor(
|
||||||
@@ -239,7 +239,7 @@ export default class CalendarPageViewModel extends TaskContainingPageViewModel {
|
|||||||
});
|
});
|
||||||
this.selectedDate.subscribeSilent(() => {
|
this.selectedDate.subscribeSilent(() => {
|
||||||
this.updateNextTask();
|
this.updateNextTask();
|
||||||
})
|
});
|
||||||
|
|
||||||
// handlers
|
// handlers
|
||||||
boardsAndTasksModel.taskHandlerManager.setHandler(
|
boardsAndTasksModel.taskHandlerManager.setHandler(
|
||||||
|
|||||||
@@ -16,9 +16,17 @@ export default class MessagePageViewModel extends Context {
|
|||||||
new React.MapState();
|
new React.MapState();
|
||||||
filteredMessageViewModels: React.ListState<ChatMessageViewModel> =
|
filteredMessageViewModels: React.ListState<ChatMessageViewModel> =
|
||||||
new React.ListState();
|
new React.ListState();
|
||||||
replyViewSelectedMessage = new React.State<ChatMessageViewModel|undefined>(undefined);
|
replyViewSelectedMessage = new React.State<
|
||||||
isReplyViewActive: React.State<boolean> = React.createProxyState([this.replyViewSelectedMessage], ()=>this.replyViewSelectedMessage.value != undefined);
|
ChatMessageViewModel | undefined
|
||||||
isReplyViewInactive = React.createProxyState([this.isReplyViewActive], ()=>!this.isReplyViewActive.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);
|
||||||
@@ -153,13 +161,13 @@ export default class MessagePageViewModel extends Context {
|
|||||||
this.replyViewSelectedMessage.value = message;
|
this.replyViewSelectedMessage.value = message;
|
||||||
this.revokeReactionFilter(false);
|
this.revokeReactionFilter(false);
|
||||||
this.setReply(message, false);
|
this.setReply(message, false);
|
||||||
}
|
};
|
||||||
|
|
||||||
resetReplyView = (): void => {
|
resetReplyView = (): void => {
|
||||||
this.replyViewSelectedMessage.value = undefined;
|
this.replyViewSelectedMessage.value = undefined;
|
||||||
this.resetReply(false);
|
this.resetReply(false);
|
||||||
this.restoreFilter();
|
this.restoreFilter();
|
||||||
}
|
};
|
||||||
|
|
||||||
setFocus = (): void => {
|
setFocus = (): void => {
|
||||||
this.focusSetter.callSubscriptions();
|
this.focusSetter.callSubscriptions();
|
||||||
@@ -178,8 +186,9 @@ export default class MessagePageViewModel extends Context {
|
|||||||
|
|
||||||
restoreFilter = (): void => {
|
restoreFilter = (): void => {
|
||||||
const previousFilter = this.chatViewModel.chatModel.getFilter() as any;
|
const previousFilter = this.chatViewModel.chatModel.getFilter() as any;
|
||||||
if (Object.values(ReactionSymbols).includes(previousFilter)) this.setReactionFilter(previousFilter);
|
if (Object.values(ReactionSymbols).includes(previousFilter))
|
||||||
}
|
this.setReactionFilter(previousFilter);
|
||||||
|
};
|
||||||
|
|
||||||
// init
|
// init
|
||||||
constructor(
|
constructor(
|
||||||
|
|||||||
@@ -30,8 +30,7 @@ export default class SettingsPageViewModel extends Context {
|
|||||||
);
|
);
|
||||||
cannotSetColor: React.State<boolean> = React.createProxyState(
|
cannotSetColor: React.State<boolean> = React.createProxyState(
|
||||||
[this.color, this.appliedColor],
|
[this.color, this.appliedColor],
|
||||||
() =>
|
() => this.color.value == this.appliedColor.value,
|
||||||
this.color.value == this.appliedColor.value,
|
|
||||||
);
|
);
|
||||||
cannotAddSecondaryChannel: React.State<boolean> = React.createProxyState(
|
cannotAddSecondaryChannel: React.State<boolean> = React.createProxyState(
|
||||||
[this.newSecondaryChannelInput],
|
[this.newSecondaryChannelInput],
|
||||||
@@ -41,11 +40,8 @@ export default class SettingsPageViewModel extends Context {
|
|||||||
|
|
||||||
// methods
|
// methods
|
||||||
setName = (): void => {
|
setName = (): void => {
|
||||||
this.chatViewModel.chatModel.setName(
|
this.chatViewModel.chatModel.setName(this.nameInput.value);
|
||||||
this.nameInput.value,
|
this.name.value = this.chatViewModel.chatModel.info.name;
|
||||||
);
|
|
||||||
this.name.value =
|
|
||||||
this.chatViewModel.chatModel.info.name;
|
|
||||||
|
|
||||||
this.chatViewModel.chatListViewModel.updateIndices();
|
this.chatViewModel.chatListViewModel.updateIndices();
|
||||||
};
|
};
|
||||||
@@ -90,8 +86,7 @@ export default class SettingsPageViewModel extends Context {
|
|||||||
|
|
||||||
// load
|
// load
|
||||||
preloadData = (): void => {
|
preloadData = (): void => {
|
||||||
this.name.value =
|
this.name.value = this.chatViewModel.chatModel.info.name;
|
||||||
this.chatViewModel.chatModel.info.name;
|
|
||||||
|
|
||||||
this.color.value = this.chatViewModel.chatModel.color;
|
this.color.value = this.chatViewModel.chatModel.color;
|
||||||
this.appliedColor.value = this.color.value;
|
this.appliedColor.value = this.color.value;
|
||||||
@@ -101,7 +96,7 @@ export default class SettingsPageViewModel extends Context {
|
|||||||
this.preloadData();
|
this.preloadData();
|
||||||
this.nameInput.value = this.name.value;
|
this.nameInput.value = this.name.value;
|
||||||
this.chatViewModel.resetColor();
|
this.chatViewModel.resetColor();
|
||||||
}
|
};
|
||||||
|
|
||||||
loadData = (): void => {
|
loadData = (): void => {
|
||||||
this.nameInput.value = this.name.value;
|
this.nameInput.value = this.name.value;
|
||||||
|
|||||||
@@ -179,7 +179,12 @@ export default class TaskPageViewModel extends ContextHost<string> {
|
|||||||
this.chatViewModel = chatViewModel;
|
this.chatViewModel = chatViewModel;
|
||||||
|
|
||||||
// filter
|
// filter
|
||||||
implementFilter(this.boardViewModels, this.boardMatches, this.boardQuery, (board) => board.name.value);
|
implementFilter(
|
||||||
|
this.boardViewModels,
|
||||||
|
this.boardMatches,
|
||||||
|
this.boardQuery,
|
||||||
|
(board) => board.name.value,
|
||||||
|
);
|
||||||
|
|
||||||
// context
|
// context
|
||||||
this.chatViewModel.registerContext(ChatPageTypes.Tasks, this);
|
this.chatViewModel.registerContext(ChatPageTypes.Tasks, this);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import TaskContainingPageViewModel from "./taskContainingPageViewModel";
|
import TaskContainingPageViewModel from "./taskContainingPageViewModel";
|
||||||
|
import CalendarPageViewModel from "./calendarPageViewModel";
|
||||||
import CoreViewModel, { Context } from "../Global/coreViewModel";
|
import CoreViewModel, { Context } from "../Global/coreViewModel";
|
||||||
import ChatViewModel from "../Chat/chatViewModel";
|
import ChatViewModel from "../Chat/chatViewModel";
|
||||||
import * as React from "../../react";
|
import * as React from "../../react";
|
||||||
@@ -8,7 +9,6 @@ import { localeCompare, padZero } from "../../Model/Utility/utility";
|
|||||||
import BoardsAndTasksModel, {
|
import BoardsAndTasksModel, {
|
||||||
TaskFileContent,
|
TaskFileContent,
|
||||||
} from "../../Model/Files/boardsAndTasksModel";
|
} from "../../Model/Files/boardsAndTasksModel";
|
||||||
import CalendarPageViewModel from "./calendarPageViewModel";
|
|
||||||
|
|
||||||
export default class TaskViewModel extends Context {
|
export default class TaskViewModel extends Context {
|
||||||
// util
|
// util
|
||||||
@@ -203,7 +203,7 @@ export default class TaskViewModel extends Context {
|
|||||||
if (this.containingViewModel instanceof CalendarPageViewModel) {
|
if (this.containingViewModel instanceof CalendarPageViewModel) {
|
||||||
this.containingViewModel.nextTask.subscribe((nextTask) => {
|
this.containingViewModel.nextTask.subscribe((nextTask) => {
|
||||||
this.isNotNext.value = nextTask != this;
|
this.isNotNext.value = nextTask != this;
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -113,4 +113,3 @@ body[theme="dark"] #background-wrapper #grass-2 {
|
|||||||
|
|
||||||
padding: var(--content-padding);
|
padding: var(--content-padding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -80,7 +80,8 @@ body:is([theme="dark"], [theme="black"]) [color]:not([color="standard"]).tile {
|
|||||||
background: hsl(var(--hue), var(--sat), var(--luma), 40%);
|
background: hsl(var(--hue), var(--sat), var(--luma), 40%);
|
||||||
}
|
}
|
||||||
|
|
||||||
body:is([theme="dark"], [theme="black"]) [color]:not([color="standard"]).background {
|
body:is([theme="dark"], [theme="black"])
|
||||||
|
[color]:not([color="standard"]).background {
|
||||||
--luma: var(--background-luma-dark);
|
--luma: var(--background-luma-dark);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +101,8 @@ body [color]:not([color="standard"]).subtle-background {
|
|||||||
background: hsl(var(--hue), 100%, var(--luma), 40%);
|
background: hsl(var(--hue), 100%, var(--luma), 40%);
|
||||||
}
|
}
|
||||||
|
|
||||||
body:is([theme="dark"], [theme="black"]) [color]:not([color="standard"]).subtle-background {
|
body:is([theme="dark"], [theme="black"])
|
||||||
|
[color]:not([color="standard"]).subtle-background {
|
||||||
--luma: var(--subtle-luma-dark);
|
--luma: var(--subtle-luma-dark);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user