move translations to CoreVM, move models to CoreVM for sentralization
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
// this file is responsible for all settings.
|
||||
|
||||
import { Languages } from "../../View/translations";
|
||||
import StorageModel, { StorageModelSubPaths, filePaths } from "./storageModel";
|
||||
|
||||
export default class SettingsModel {
|
||||
@@ -8,6 +9,7 @@ export default class SettingsModel {
|
||||
// data
|
||||
username: string;
|
||||
firstDayOfWeek: string;
|
||||
language: string;
|
||||
|
||||
// storage
|
||||
setName(newValue: string): void {
|
||||
@@ -28,6 +30,15 @@ export default class SettingsModel {
|
||||
this.storageModel.write(path, newValue);
|
||||
}
|
||||
|
||||
setLanguage(newValue: Languages): void {
|
||||
this.language = newValue;
|
||||
const path = StorageModel.getPath(
|
||||
StorageModelSubPaths.SettingsModel,
|
||||
filePaths.settingsModel.language,
|
||||
);
|
||||
this.storageModel.write(path, newValue);
|
||||
}
|
||||
|
||||
// load
|
||||
loadUsernam(): void {
|
||||
const path = StorageModel.getPath(
|
||||
@@ -47,6 +58,15 @@ export default class SettingsModel {
|
||||
this.firstDayOfWeek = content ?? "0";
|
||||
}
|
||||
|
||||
loadLanguage(): void {
|
||||
const path = StorageModel.getPath(
|
||||
StorageModelSubPaths.SettingsModel,
|
||||
filePaths.settingsModel.language,
|
||||
);
|
||||
const content = this.storageModel.read(path);
|
||||
this.language = content ?? SettingsModel.getSystemLanguage();
|
||||
}
|
||||
|
||||
// init
|
||||
constructor(storageModel: StorageModel) {
|
||||
this.storageModel = storageModel;
|
||||
@@ -54,4 +74,15 @@ export default class SettingsModel {
|
||||
this.loadUsernam();
|
||||
this.loadFirstDayofWeek();
|
||||
}
|
||||
|
||||
static getSystemLanguage(): Languages {
|
||||
switch (navigator.language.substring(0, 2)) {
|
||||
case "de":
|
||||
return Languages.German;
|
||||
case "es":
|
||||
return Languages.Spanish;
|
||||
default:
|
||||
return Languages.English;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,5 +265,6 @@ export const filePaths = {
|
||||
settingsModel: {
|
||||
username: ["user-name"],
|
||||
firstDayOfWeek: ["first-day-of-week"],
|
||||
language: ["language"],
|
||||
},
|
||||
};
|
||||
|
||||
+10
-15
@@ -14,13 +14,10 @@ import {
|
||||
parseOrFallback,
|
||||
} from "../Model/Utility/utility";
|
||||
|
||||
import ChatListModel from "../Model/Chat/chatListModel";
|
||||
import ConnectionModel from "../Model/Global/connectionModel";
|
||||
import FileModel from "../Model/Files/fileModel";
|
||||
import SettingsModel from "../Model/Global/settingsModel";
|
||||
import { checkMatchesObjectStructure } from "../Model/Utility/typeSafety";
|
||||
import { translations } from "../View/translations";
|
||||
import { v4 } from "uuid";
|
||||
import CoreViewModel from "../ViewModel/Global/coreViewModel";
|
||||
|
||||
export default class v1Upgrader {
|
||||
// general
|
||||
@@ -28,7 +25,7 @@ export default class v1Upgrader {
|
||||
const name: string | null = getLocalStorageItemAndClear("sender-name");
|
||||
if (name != null) {
|
||||
const parsedName: string = parseOrFallback(name);
|
||||
this.settingsModel.setName(parsedName);
|
||||
this.coreViewModel.settingsModel.setName(parsedName);
|
||||
}
|
||||
|
||||
const firstDayOfWeek: string | null =
|
||||
@@ -36,7 +33,9 @@ export default class v1Upgrader {
|
||||
if (firstDayOfWeek != null) {
|
||||
const parsedFirstDayOfWeek: string =
|
||||
parseOrFallback(firstDayOfWeek);
|
||||
this.settingsModel.setFirstDayOfWeek(parsedFirstDayOfWeek);
|
||||
this.coreViewModel.settingsModel.setFirstDayOfWeek(
|
||||
parsedFirstDayOfWeek,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -48,7 +47,7 @@ export default class v1Upgrader {
|
||||
const previousAddresses: any[] = parseArray(previousAddressString);
|
||||
for (const address of previousAddresses) {
|
||||
if (typeof address != "string") continue;
|
||||
this.connectionModel.storeAddress(address);
|
||||
this.coreViewModel.connectionModel.storeAddress(address);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -75,7 +74,7 @@ export default class v1Upgrader {
|
||||
|
||||
// create chat
|
||||
const chatModel: ChatModel =
|
||||
this.chatListModel.createChat(parsedPriamryChannel);
|
||||
this.coreViewModel.chatListModel.createChat(parsedPriamryChannel);
|
||||
|
||||
// secondary channels
|
||||
const secondaryChannelString: string | null =
|
||||
@@ -140,7 +139,7 @@ export default class v1Upgrader {
|
||||
};
|
||||
chatModel.addMessage(convertedChatMessage);
|
||||
if (status == ChatMessageStatuses.Outbox) {
|
||||
this.connectionModel.sendMessageOrStore(
|
||||
this.coreViewModel.connectionModel.sendMessageOrStore(
|
||||
convertedChatMessage,
|
||||
);
|
||||
}
|
||||
@@ -161,7 +160,7 @@ export default class v1Upgrader {
|
||||
const addObjects = (potentialObjects: any[]): void => {
|
||||
const board: BoardInfoFileContent =
|
||||
chatModel.fileModel.boardsAndTasksModel.createBoard(
|
||||
translations.updater.migrated,
|
||||
this.coreViewModel.translations.updater.migrated,
|
||||
);
|
||||
chatModel.fileModel.boardsAndTasksModel.updateBoard(board);
|
||||
|
||||
@@ -216,11 +215,7 @@ export default class v1Upgrader {
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(
|
||||
public settingsModel: SettingsModel,
|
||||
public connectionModel: ConnectionModel,
|
||||
public chatListModel: ChatListModel,
|
||||
) {
|
||||
constructor(public coreViewModel: CoreViewModel) {
|
||||
this.migrateSettings();
|
||||
this.migrateConnections();
|
||||
this.migrateChats();
|
||||
|
||||
@@ -11,9 +11,12 @@ import { TaskCategoryBulkChangeViewModel } from "../../ViewModel/Utility/taskPro
|
||||
import TaskViewModel from "../../ViewModel/Pages/taskViewModel";
|
||||
import { TaskViewModelToEntry } from "../Components/taskEntry";
|
||||
import { allowDrop } from "../utility";
|
||||
import { translations } from "../translations";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function BoardKanbanPage(boardViewModel: BoardViewModel) {
|
||||
export function BoardKanbanPage(
|
||||
coreViewModel: CoreViewModel,
|
||||
boardViewModel: BoardViewModel,
|
||||
) {
|
||||
return PropertyValueList(
|
||||
"category",
|
||||
(taskViewModel: TaskViewModel) => taskViewModel.task,
|
||||
@@ -30,7 +33,12 @@ export function BoardKanbanPage(boardViewModel: BoardViewModel) {
|
||||
sortedCategories,
|
||||
categoryName,
|
||||
);
|
||||
return Column(categoryName, index, boardViewModel);
|
||||
return Column(
|
||||
coreViewModel,
|
||||
categoryName,
|
||||
index,
|
||||
boardViewModel,
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -44,6 +52,7 @@ export function BoardKanbanPage(boardViewModel: BoardViewModel) {
|
||||
}
|
||||
|
||||
function Column(
|
||||
coreViewModel: CoreViewModel,
|
||||
categoryName: string,
|
||||
index: React.State<number>,
|
||||
boardViewModel: BoardViewModel,
|
||||
@@ -72,7 +81,7 @@ function Column(
|
||||
<div class="flex-row width-input">
|
||||
<input
|
||||
placeholder={
|
||||
translations.chatPage.task
|
||||
coreViewModel.translations.chatPage.task
|
||||
.renameCategoryInputPlaceholder
|
||||
}
|
||||
bind:value={viewModel.inputValue}
|
||||
|
||||
@@ -11,10 +11,13 @@ import { BoardViewToggleButton } from "../Components/boardViewToggleButton";
|
||||
import { SearchModal } from "../Modals/searchModal";
|
||||
import { TaskSettingsModal } from "../Modals/taskSettingsModal";
|
||||
import { TaskViewModelToEntry } from "../Components/taskEntry";
|
||||
import { translations } from "../translations";
|
||||
import { setFocusWithDelay } from "../utility";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function BoardPage(boardViewModel: BoardViewModel) {
|
||||
export function BoardPage(
|
||||
coreViewModel: CoreViewModel,
|
||||
boardViewModel: BoardViewModel,
|
||||
) {
|
||||
boardViewModel.loadData();
|
||||
|
||||
// main content
|
||||
@@ -23,10 +26,10 @@ export function BoardPage(boardViewModel: BoardViewModel) {
|
||||
() => {
|
||||
switch (boardViewModel.selectedPage.value) {
|
||||
case BoardPageTypes.Kanban: {
|
||||
return BoardKanbanPage(boardViewModel);
|
||||
return BoardKanbanPage(coreViewModel, boardViewModel);
|
||||
}
|
||||
case BoardPageTypes.StatusGrid: {
|
||||
return BoardStatusGridPage(boardViewModel);
|
||||
return BoardStatusGridPage(coreViewModel, boardViewModel);
|
||||
}
|
||||
default: {
|
||||
return (
|
||||
@@ -53,6 +56,7 @@ export function BoardPage(boardViewModel: BoardViewModel) {
|
||||
setFocusWithDelay();
|
||||
|
||||
return TaskSettingsModal(
|
||||
coreViewModel,
|
||||
boardViewModel.selectedTaskViewModel.value,
|
||||
);
|
||||
}
|
||||
@@ -66,7 +70,7 @@ export function BoardPage(boardViewModel: BoardViewModel) {
|
||||
<button
|
||||
class="ghost board-close-button"
|
||||
aria-label={
|
||||
translations.chatPage.task
|
||||
coreViewModel.translations.chatPage.task
|
||||
.closeBoardButtonAudioLabel
|
||||
}
|
||||
on:click={boardViewModel.close}
|
||||
@@ -76,7 +80,7 @@ export function BoardPage(boardViewModel: BoardViewModel) {
|
||||
<button
|
||||
class="ghost board-toggle-button inset-outline"
|
||||
aria-label={
|
||||
translations.chatPage.task
|
||||
coreViewModel.translations.chatPage.task
|
||||
.toggleBoardButtonAudioLabel
|
||||
}
|
||||
on:click={
|
||||
@@ -91,7 +95,8 @@ export function BoardPage(boardViewModel: BoardViewModel) {
|
||||
<button
|
||||
class="ghost"
|
||||
aria-label={
|
||||
translations.chatPage.task.boardSettingsHeadline
|
||||
coreViewModel.translations.chatPage.task
|
||||
.boardSettingsHeadline
|
||||
}
|
||||
on:click={boardViewModel.showSettings}
|
||||
>
|
||||
@@ -100,19 +105,22 @@ export function BoardPage(boardViewModel: BoardViewModel) {
|
||||
</span>
|
||||
<span class="scroll-h ribbon">
|
||||
{BoardViewToggleButton(
|
||||
translations.chatPage.task.listViewButtonAudioLabel,
|
||||
coreViewModel.translations.chatPage.task
|
||||
.listViewButtonAudioLabel,
|
||||
"view_list",
|
||||
BoardPageTypes.List,
|
||||
boardViewModel,
|
||||
)}
|
||||
{BoardViewToggleButton(
|
||||
translations.chatPage.task.kanbanViewButtonAudioLabel,
|
||||
coreViewModel.translations.chatPage.task
|
||||
.kanbanViewButtonAudioLabel,
|
||||
"view_kanban",
|
||||
BoardPageTypes.Kanban,
|
||||
boardViewModel,
|
||||
)}
|
||||
{BoardViewToggleButton(
|
||||
translations.chatPage.task.statusViewButtonAudioLabel,
|
||||
coreViewModel.translations.chatPage.task
|
||||
.statusViewButtonAudioLabel,
|
||||
"grid_view",
|
||||
BoardPageTypes.StatusGrid,
|
||||
boardViewModel,
|
||||
@@ -122,7 +130,7 @@ export function BoardPage(boardViewModel: BoardViewModel) {
|
||||
<button
|
||||
class="ghost"
|
||||
aria-label={
|
||||
translations.chatPage.task
|
||||
coreViewModel.translations.chatPage.task
|
||||
.filterTasksButtonAudioLabel
|
||||
}
|
||||
on:click={boardViewModel.showFilterModal}
|
||||
@@ -132,7 +140,7 @@ export function BoardPage(boardViewModel: BoardViewModel) {
|
||||
<button
|
||||
class="ghost"
|
||||
aria-label={
|
||||
translations.chatPage.task
|
||||
coreViewModel.translations.chatPage.task
|
||||
.createTaskButtonAudioLabel
|
||||
}
|
||||
on:click={boardViewModel.createTask}
|
||||
@@ -143,10 +151,11 @@ export function BoardPage(boardViewModel: BoardViewModel) {
|
||||
</div>
|
||||
<div class="content main-content" children:set={mainContent}></div>
|
||||
|
||||
{BoardSettingsModal(boardViewModel)}
|
||||
{BoardSettingsModal(coreViewModel, boardViewModel)}
|
||||
{SearchModal(
|
||||
coreViewModel,
|
||||
boardViewModel.searchViewModel,
|
||||
translations.chatPage.task.filterTasksHeadline,
|
||||
coreViewModel.translations.chatPage.task.filterTasksHeadline,
|
||||
TaskViewModelToEntry,
|
||||
boardViewModel.isPresentingFilterModal,
|
||||
)}
|
||||
|
||||
@@ -16,9 +16,12 @@ import { FilteredList } from "../Components/filteredList";
|
||||
import TaskViewModel from "../../ViewModel/Pages/taskViewModel";
|
||||
import { TaskViewModelToEntry } from "../Components/taskEntry";
|
||||
import { allowDrop } from "../utility";
|
||||
import { translations } from "../translations";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function BoardStatusGridPage(boardViewModel: BoardViewModel) {
|
||||
export function BoardStatusGridPage(
|
||||
coreViewModel: CoreViewModel,
|
||||
boardViewModel: BoardViewModel,
|
||||
) {
|
||||
const statuses: React.ListState<string> = new React.ListState();
|
||||
const sortedStatuses: React.State<string[]> =
|
||||
createSortedPropertyValueState(statuses);
|
||||
@@ -36,7 +39,7 @@ export function BoardStatusGridPage(boardViewModel: BoardViewModel) {
|
||||
statusName: string,
|
||||
) => {
|
||||
const index = createPropertyValueIndexState(sortedStatuses, statusName);
|
||||
return StatusNameCell(statusName, index, boardViewModel);
|
||||
return StatusNameCell(coreViewModel, statusName, index, boardViewModel);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -63,6 +66,7 @@ export function BoardStatusGridPage(boardViewModel: BoardViewModel) {
|
||||
);
|
||||
|
||||
return CategoryRow(
|
||||
coreViewModel,
|
||||
categoryName,
|
||||
index,
|
||||
statuses,
|
||||
@@ -84,6 +88,7 @@ export function BoardStatusGridPage(boardViewModel: BoardViewModel) {
|
||||
}
|
||||
|
||||
function StatusNameCell(
|
||||
coreViewModel: CoreViewModel,
|
||||
statusName: string,
|
||||
index: React.State<number>,
|
||||
boardViewModel: BoardViewModel,
|
||||
@@ -118,7 +123,8 @@ function StatusNameCell(
|
||||
<div class="property-input-wrapper">
|
||||
<input
|
||||
placeholder={
|
||||
translations.chatPage.task.renameStatusInputPlaceholder
|
||||
coreViewModel.translations.chatPage.task
|
||||
.renameStatusInputPlaceholder
|
||||
}
|
||||
bind:value={viewModel.inputValue}
|
||||
on:enter={viewModel.set}
|
||||
@@ -142,6 +148,7 @@ function StatusNameCell(
|
||||
}
|
||||
|
||||
function CategoryRow(
|
||||
coreViewModel: CoreViewModel,
|
||||
categoryName: string,
|
||||
index: React.State<number>,
|
||||
allStatuses: React.ListState<string>,
|
||||
@@ -180,7 +187,7 @@ function CategoryRow(
|
||||
<div class="property-input-wrapper">
|
||||
<input
|
||||
placeholder={
|
||||
translations.chatPage.task
|
||||
coreViewModel.translations.chatPage.task
|
||||
.renameCategoryInputPlaceholder
|
||||
}
|
||||
bind:value={viewModel.inputValue}
|
||||
|
||||
@@ -7,10 +7,13 @@ import CalendarPageViewModel from "../../ViewModel/Pages/calendarPageViewModel";
|
||||
import { MonthGrid } from "../Components/monthGrid";
|
||||
import { TaskSettingsModal } from "../Modals/taskSettingsModal";
|
||||
import { TaskViewModelToEntry } from "../Components/taskEntry";
|
||||
import { translations } from "../translations";
|
||||
import { setFocusWithDelay } from "../utility";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function CalendarPage(calendarPageViewModel: CalendarPageViewModel) {
|
||||
export function CalendarPage(
|
||||
coreViewModel: CoreViewModel,
|
||||
calendarPageViewModel: CalendarPageViewModel,
|
||||
) {
|
||||
calendarPageViewModel.loadData();
|
||||
|
||||
const mainContent = React.createProxyState(
|
||||
@@ -30,6 +33,7 @@ export function CalendarPage(calendarPageViewModel: CalendarPageViewModel) {
|
||||
}
|
||||
|
||||
return MonthGrid(
|
||||
coreViewModel,
|
||||
monthGrid,
|
||||
calendarPageViewModel.selectedDate,
|
||||
drop,
|
||||
@@ -58,8 +62,8 @@ export function CalendarPage(calendarPageViewModel: CalendarPageViewModel) {
|
||||
<div class="width-100 height-100 flex-column justify-center align-center">
|
||||
<span class="secondary slide-up">
|
||||
{
|
||||
translations.chatPage.calendar
|
||||
.noEvents
|
||||
coreViewModel.translations.chatPage
|
||||
.calendar.noEvents
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
@@ -99,6 +103,7 @@ export function CalendarPage(calendarPageViewModel: CalendarPageViewModel) {
|
||||
setFocusWithDelay();
|
||||
|
||||
return TaskSettingsModal(
|
||||
coreViewModel,
|
||||
calendarPageViewModel.selectedTaskViewModel.value,
|
||||
);
|
||||
}
|
||||
@@ -114,7 +119,7 @@ export function CalendarPage(calendarPageViewModel: CalendarPageViewModel) {
|
||||
<button
|
||||
class="ghost"
|
||||
aria-label={
|
||||
translations.chatPage.calendar
|
||||
coreViewModel.translations.chatPage.calendar
|
||||
.todayButtonAudioLabel
|
||||
}
|
||||
on:click={calendarPageViewModel.showToday}
|
||||
@@ -126,7 +131,7 @@ export function CalendarPage(calendarPageViewModel: CalendarPageViewModel) {
|
||||
<button
|
||||
class="ghost"
|
||||
aria-label={
|
||||
translations.chatPage.calendar
|
||||
coreViewModel.translations.chatPage.calendar
|
||||
.previousMonthButtonAudioLabel
|
||||
}
|
||||
on:click={
|
||||
@@ -140,12 +145,12 @@ export function CalendarPage(calendarPageViewModel: CalendarPageViewModel) {
|
||||
class="year-input"
|
||||
type="number"
|
||||
aria-label={
|
||||
translations.chatPage.calendar
|
||||
.yearInputAudioLabel
|
||||
coreViewModel.translations.chatPage
|
||||
.calendar.yearInputAudioLabel
|
||||
}
|
||||
placeholder={
|
||||
translations.chatPage.calendar
|
||||
.yearInputPlaceholder
|
||||
coreViewModel.translations.chatPage
|
||||
.calendar.yearInputPlaceholder
|
||||
}
|
||||
bind:value={
|
||||
calendarPageViewModel.selectedYear
|
||||
@@ -155,12 +160,12 @@ export function CalendarPage(calendarPageViewModel: CalendarPageViewModel) {
|
||||
class="month-input"
|
||||
type="number"
|
||||
aria-label={
|
||||
translations.chatPage.calendar
|
||||
.monthInputAudioLabel
|
||||
coreViewModel.translations.chatPage
|
||||
.calendar.monthInputAudioLabel
|
||||
}
|
||||
placeholder={
|
||||
translations.chatPage.calendar
|
||||
.monthInputPlaceholder
|
||||
coreViewModel.translations.chatPage
|
||||
.calendar.monthInputPlaceholder
|
||||
}
|
||||
bind:value={
|
||||
calendarPageViewModel.selectedMonth
|
||||
@@ -170,7 +175,7 @@ export function CalendarPage(calendarPageViewModel: CalendarPageViewModel) {
|
||||
<button
|
||||
class="ghost"
|
||||
aria-label={
|
||||
translations.chatPage.calendar
|
||||
coreViewModel.translations.chatPage.calendar
|
||||
.nextMonthButtonAudioLabel
|
||||
}
|
||||
on:click={calendarPageViewModel.showNextMonth}
|
||||
@@ -182,7 +187,7 @@ export function CalendarPage(calendarPageViewModel: CalendarPageViewModel) {
|
||||
<button
|
||||
class="ghost"
|
||||
aria-label={
|
||||
translations.chatPage.task
|
||||
coreViewModel.translations.chatPage.task
|
||||
.createTaskButtonAudioLabel
|
||||
}
|
||||
on:click={calendarPageViewModel.createEvent}
|
||||
|
||||
@@ -2,12 +2,21 @@ import "./messagePage.css";
|
||||
|
||||
import * as React from "bloatless-react";
|
||||
|
||||
import { ChatMessageViewModelToView } from "../Components/chatMessage";
|
||||
import MessagePageViewModel from "../../ViewModel/Pages/messagePageViewModel";
|
||||
import { translations } from "../translations";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
|
||||
import { ChatMessage } from "../Components/chatMessage";
|
||||
|
||||
export function MessagePage(messagePageViewModel: MessagePageViewModel) {
|
||||
export function MessagePage(
|
||||
coreViewModel: CoreViewModel,
|
||||
messagePageViewModel: MessagePageViewModel,
|
||||
) {
|
||||
messagePageViewModel.loadData();
|
||||
const ChatMessageViewModelToView: React.StateItemConverter<
|
||||
ChatMessageViewModel
|
||||
> = (chatMessageViewModel: ChatMessageViewModel) => {
|
||||
return ChatMessage(coreViewModel, chatMessageViewModel);
|
||||
};
|
||||
|
||||
const messageContainer = (
|
||||
<div
|
||||
@@ -45,7 +54,10 @@ export function MessagePage(messagePageViewModel: MessagePageViewModel) {
|
||||
<div class="pane">
|
||||
<div class="toolbar">
|
||||
<span class="title">
|
||||
{translations.chatPage.message.messagesHeadline}
|
||||
{
|
||||
coreViewModel.translations.chatPage.message
|
||||
.messagesHeadline
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
<div class="content">
|
||||
@@ -61,14 +73,16 @@ export function MessagePage(messagePageViewModel: MessagePageViewModel) {
|
||||
messagePageViewModel.sendMessage
|
||||
}
|
||||
placeholder={
|
||||
translations.chatPage.message
|
||||
coreViewModel.translations.chatPage
|
||||
.message
|
||||
.composerInputPlaceholder
|
||||
}
|
||||
></input>
|
||||
<button
|
||||
class="primary"
|
||||
aria-label={
|
||||
translations.chatPage.message
|
||||
coreViewModel.translations.chatPage
|
||||
.message
|
||||
.sendMessageButtonAudioLabel
|
||||
}
|
||||
on:click={
|
||||
|
||||
@@ -5,17 +5,25 @@ import { ColorPicker } from "../Components/colorPicker";
|
||||
import { DangerousActionButton } from "../Components/dangerousActionButton";
|
||||
import { DeletableListItem } from "../Components/deletableListItem";
|
||||
import SettingsPageViewModel from "../../ViewModel/Pages/settingsPageViewModel";
|
||||
import { translations } from "../translations";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function SettingsPage(settingsPageViewModel: SettingsPageViewModel) {
|
||||
export function SettingsPage(
|
||||
coreViewModel: CoreViewModel,
|
||||
settingsPageViewModel: SettingsPageViewModel,
|
||||
) {
|
||||
settingsPageViewModel.loadData();
|
||||
|
||||
const secondaryChannelConverter: React.StateItemConverter<string> = (
|
||||
secondaryChannel: string,
|
||||
) => {
|
||||
return DeletableListItem(secondaryChannel, <span></span>, () => {
|
||||
settingsPageViewModel.removeSecondaryChannel(secondaryChannel);
|
||||
});
|
||||
return DeletableListItem(
|
||||
coreViewModel,
|
||||
secondaryChannel,
|
||||
<span></span>,
|
||||
() => {
|
||||
settingsPageViewModel.removeSecondaryChannel(secondaryChannel);
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -24,7 +32,10 @@ export function SettingsPage(settingsPageViewModel: SettingsPageViewModel) {
|
||||
<div class="pane">
|
||||
<div class="toolbar">
|
||||
<span class="title">
|
||||
{translations.chatPage.settings.settingsHeadline}
|
||||
{
|
||||
coreViewModel.translations.chatPage.settings
|
||||
.settingsHeadline
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
<div class="content">
|
||||
@@ -33,8 +44,8 @@ export function SettingsPage(settingsPageViewModel: SettingsPageViewModel) {
|
||||
<div>
|
||||
<span>
|
||||
{
|
||||
translations.chatPage.settings
|
||||
.primaryChannelLabel
|
||||
coreViewModel.translations.chatPage
|
||||
.settings.primaryChannelLabel
|
||||
}
|
||||
</span>
|
||||
<input
|
||||
@@ -51,7 +62,7 @@ export function SettingsPage(settingsPageViewModel: SettingsPageViewModel) {
|
||||
<button
|
||||
class="width-50"
|
||||
aria-label={
|
||||
translations.chatPage.settings
|
||||
coreViewModel.translations.chatPage.settings
|
||||
.setPrimaryChannelButtonAudioLabel
|
||||
}
|
||||
on:click={
|
||||
@@ -61,7 +72,7 @@ export function SettingsPage(settingsPageViewModel: SettingsPageViewModel) {
|
||||
settingsPageViewModel.cannotSetPrimaryChannel
|
||||
}
|
||||
>
|
||||
{translations.general.setButton}
|
||||
{coreViewModel.translations.general.setButton}
|
||||
<span class="icon">check</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -71,11 +82,11 @@ export function SettingsPage(settingsPageViewModel: SettingsPageViewModel) {
|
||||
<div class="flex-row width-input margin-bottom">
|
||||
<input
|
||||
aria-label={
|
||||
translations.chatPage.settings
|
||||
coreViewModel.translations.chatPage.settings
|
||||
.newSecondaryChannelAudioLabel
|
||||
}
|
||||
placeholder={
|
||||
translations.chatPage.settings
|
||||
coreViewModel.translations.chatPage.settings
|
||||
.newSecondaryChannelPlaceholder
|
||||
}
|
||||
bind:value={
|
||||
@@ -88,7 +99,7 @@ export function SettingsPage(settingsPageViewModel: SettingsPageViewModel) {
|
||||
<button
|
||||
class="primary"
|
||||
aria-label={
|
||||
translations.chatPage.settings
|
||||
coreViewModel.translations.chatPage.settings
|
||||
.addSecondaryChannelButtonAudioLabel
|
||||
}
|
||||
on:click={
|
||||
@@ -117,8 +128,8 @@ export function SettingsPage(settingsPageViewModel: SettingsPageViewModel) {
|
||||
<div>
|
||||
<span>
|
||||
{
|
||||
translations.chatPage.settings
|
||||
.encryptionKeyLabel
|
||||
coreViewModel.translations.chatPage
|
||||
.settings.encryptionKeyLabel
|
||||
}
|
||||
</span>
|
||||
<input
|
||||
@@ -138,7 +149,7 @@ export function SettingsPage(settingsPageViewModel: SettingsPageViewModel) {
|
||||
<button
|
||||
class="width-50"
|
||||
aria-label={
|
||||
translations.chatPage.settings
|
||||
coreViewModel.translations.chatPage.settings
|
||||
.setEncryptionKeyButtonAudioLabel
|
||||
}
|
||||
on:click={
|
||||
@@ -148,7 +159,7 @@ export function SettingsPage(settingsPageViewModel: SettingsPageViewModel) {
|
||||
settingsPageViewModel.cannotSetEncryptionKey
|
||||
}
|
||||
>
|
||||
{translations.general.setButton}
|
||||
{coreViewModel.translations.general.setButton}
|
||||
<span class="icon">check</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -160,7 +171,10 @@ export function SettingsPage(settingsPageViewModel: SettingsPageViewModel) {
|
||||
settingsPageViewModel.shouldShowEncryptionKey
|
||||
}
|
||||
></input>
|
||||
{translations.chatPage.settings.showEncryptionKey}
|
||||
{
|
||||
coreViewModel.translations.chatPage.settings
|
||||
.showEncryptionKey
|
||||
}
|
||||
</label>
|
||||
|
||||
<hr></hr>
|
||||
@@ -171,7 +185,9 @@ export function SettingsPage(settingsPageViewModel: SettingsPageViewModel) {
|
||||
|
||||
<div class="width-input">
|
||||
{DangerousActionButton(
|
||||
translations.chatPage.settings.deleteChatButton,
|
||||
coreViewModel,
|
||||
coreViewModel.translations.chatPage.settings
|
||||
.deleteChatButton,
|
||||
"chat_error",
|
||||
settingsPageViewModel.remove,
|
||||
)}
|
||||
|
||||
@@ -5,9 +5,12 @@ import * as React from "bloatless-react";
|
||||
import { BoardPage } from "./boardPage";
|
||||
import { BoardViewModelToEntry } from "../Components/boardEntry";
|
||||
import TaskPageViewModel from "../../ViewModel/Pages/taskPageViewModel";
|
||||
import { translations } from "../translations";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function TaskPage(taskPageViewModel: TaskPageViewModel) {
|
||||
export function TaskPage(
|
||||
coreViewModel: CoreViewModel,
|
||||
taskPageViewModel: TaskPageViewModel,
|
||||
) {
|
||||
taskPageViewModel.loadData();
|
||||
|
||||
const isShowingBoard = React.createProxyState(
|
||||
@@ -23,7 +26,10 @@ export function TaskPage(taskPageViewModel: TaskPageViewModel) {
|
||||
return (
|
||||
<div class="pane align-center justify-center">
|
||||
<span class="secondary">
|
||||
{translations.chatPage.task.noBoardSelected}
|
||||
{
|
||||
coreViewModel.translations.chatPage.task
|
||||
.noBoardSelected
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
@@ -34,13 +40,16 @@ export function TaskPage(taskPageViewModel: TaskPageViewModel) {
|
||||
return (
|
||||
<div class="pane align-center justify-center">
|
||||
<span class="secondary">
|
||||
{translations.chatPage.task.boardNotFound}
|
||||
{
|
||||
coreViewModel.translations.chatPage.task
|
||||
.boardNotFound
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return BoardPage(selectedBoard);
|
||||
return BoardPage(coreViewModel, selectedBoard);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -63,14 +72,14 @@ export function TaskPage(taskPageViewModel: TaskPageViewModel) {
|
||||
bind:value={taskPageViewModel.newBoardNameInput}
|
||||
on:enter={taskPageViewModel.createBoard}
|
||||
placeholder={
|
||||
translations.chatPage.task
|
||||
coreViewModel.translations.chatPage.task
|
||||
.newBoardNamePlaceholder
|
||||
}
|
||||
></input>
|
||||
<button
|
||||
class="primary"
|
||||
aria-label={
|
||||
translations.chatPage.task
|
||||
coreViewModel.translations.chatPage.task
|
||||
.createBoardButtonAudioLabel
|
||||
}
|
||||
on:click={taskPageViewModel.createBoard}
|
||||
|
||||
@@ -3,10 +3,13 @@ import * as React from "bloatless-react";
|
||||
import { ChatMessageInfoModal } from "../Modals/chatMessageInfoModal";
|
||||
import { ChatMessageStatuses } from "../../Model/Chat/chatModel";
|
||||
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
|
||||
import { translations } from "../translations";
|
||||
import { MessageReactionButtonRow } from "./messageReactionButtonRow";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function ChatMessage(chatMessageViewModel: ChatMessageViewModel) {
|
||||
export function ChatMessage(
|
||||
coreViewModel: CoreViewModel,
|
||||
chatMessageViewModel: ChatMessageViewModel,
|
||||
) {
|
||||
const statusIcon = React.createProxyState(
|
||||
[chatMessageViewModel.status],
|
||||
() => {
|
||||
@@ -50,7 +53,7 @@ export function ChatMessage(chatMessageViewModel: ChatMessageViewModel) {
|
||||
<button
|
||||
on:click={chatMessageViewModel.showInfoModal}
|
||||
aria-label={
|
||||
translations.chatPage.message
|
||||
coreViewModel.translations.chatPage.message
|
||||
.showMessageInfoButtonAudioLabel
|
||||
}
|
||||
>
|
||||
@@ -58,14 +61,8 @@ export function ChatMessage(chatMessageViewModel: ChatMessageViewModel) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{MessageReactionButtonRow(chatMessageViewModel)}
|
||||
{ChatMessageInfoModal(chatMessageViewModel)}
|
||||
{MessageReactionButtonRow(coreViewModel, chatMessageViewModel)}
|
||||
{ChatMessageInfoModal(coreViewModel, chatMessageViewModel)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const ChatMessageViewModelToView: React.StateItemConverter<
|
||||
ChatMessageViewModel
|
||||
> = (chatMessageViewModel: ChatMessageViewModel) => {
|
||||
return ChatMessage(chatMessageViewModel);
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as React from "bloatless-react";
|
||||
|
||||
import { translations } from "../translations";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function DangerousActionButton(
|
||||
coreViewModel: CoreViewModel,
|
||||
label: string,
|
||||
icon: string,
|
||||
action: () => void,
|
||||
@@ -23,7 +23,7 @@ export function DangerousActionButton(
|
||||
return (
|
||||
<div class="flex-row">
|
||||
<button class="flex" on:click={abort} toggle:hidden={cannotConfirm}>
|
||||
{translations.general.abortButton}
|
||||
{coreViewModel.translations.general.abortButton}
|
||||
<span class="icon">undo</span>
|
||||
</button>
|
||||
<button
|
||||
@@ -39,7 +39,7 @@ export function DangerousActionButton(
|
||||
on:click={action}
|
||||
toggle:hidden={cannotConfirm}
|
||||
>
|
||||
{translations.general.confirmButton}
|
||||
{coreViewModel.translations.general.confirmButton}
|
||||
<span class="icon">warning</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as React from "bloatless-react";
|
||||
|
||||
import { translations } from "../translations";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function DeletableListItem(
|
||||
coreViewModel: CoreViewModel,
|
||||
text: string,
|
||||
primaryButton: HTMLElement,
|
||||
ondelete: () => void,
|
||||
@@ -16,7 +16,10 @@ export function DeletableListItem(
|
||||
|
||||
<button
|
||||
class="danger"
|
||||
aria-label={translations.general.deleteItemButtonAudioLabel}
|
||||
aria-label={
|
||||
coreViewModel.translations.general
|
||||
.deleteItemButtonAudioLabel
|
||||
}
|
||||
on:click={ondelete}
|
||||
>
|
||||
<span class="icon">delete</span>
|
||||
|
||||
@@ -26,7 +26,8 @@ export function DirectoryItemList(
|
||||
function loadItems() {
|
||||
items.clear();
|
||||
|
||||
const directoryItems = storageViewModel.storageModel.list(path);
|
||||
const directoryItems =
|
||||
storageViewModel.coreViewModel.storageModel.list(path);
|
||||
|
||||
for (const directoryItem of directoryItems) {
|
||||
const itemPath = [...path, directoryItem];
|
||||
|
||||
@@ -4,9 +4,10 @@ import {
|
||||
ReactionSymbols,
|
||||
} from "../../Model/Chat/chatModel";
|
||||
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
|
||||
import { translations } from "../translations";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function MessageReactionButton(
|
||||
coreViewModel: CoreViewModel,
|
||||
chatMessageViewModel: ChatMessageViewModel,
|
||||
content: ReactionSymbols,
|
||||
) {
|
||||
@@ -31,37 +32,44 @@ export function MessageReactionButton(
|
||||
|
||||
switch (content) {
|
||||
case ReactionSymbols.ThumbsUp: {
|
||||
audioLabel = translations.chatPage.message.thumbsUpReaction;
|
||||
audioLabel =
|
||||
coreViewModel.translations.chatPage.message.thumbsUpReaction;
|
||||
count = chatMessageViewModel.reactionsThumbsUpCount;
|
||||
reactionState = chatMessageViewModel.reactionsThumbsUp;
|
||||
break;
|
||||
}
|
||||
case ReactionSymbols.Check: {
|
||||
audioLabel = translations.chatPage.message.checkReaction;
|
||||
audioLabel =
|
||||
coreViewModel.translations.chatPage.message.checkReaction;
|
||||
count = chatMessageViewModel.reactionsCheckCount;
|
||||
reactionState = chatMessageViewModel.reactionsCheck;
|
||||
break;
|
||||
}
|
||||
case ReactionSymbols.Stop: {
|
||||
audioLabel = translations.chatPage.message.stopReaction;
|
||||
audioLabel =
|
||||
coreViewModel.translations.chatPage.message.stopReaction;
|
||||
count = chatMessageViewModel.reactionsStopCount;
|
||||
reactionState = chatMessageViewModel.reactionsStop;
|
||||
break;
|
||||
}
|
||||
case ReactionSymbols.Attention: {
|
||||
audioLabel = translations.chatPage.message.attentionReaction;
|
||||
audioLabel =
|
||||
coreViewModel.translations.chatPage.message.attentionReaction;
|
||||
count = chatMessageViewModel.reactionsAttentionCount;
|
||||
reactionState = chatMessageViewModel.reactionsAttention;
|
||||
break;
|
||||
}
|
||||
case ReactionSymbols.DoubleAttention: {
|
||||
audioLabel = translations.chatPage.message.doubleAttentionReaction;
|
||||
audioLabel =
|
||||
coreViewModel.translations.chatPage.message
|
||||
.doubleAttentionReaction;
|
||||
count = chatMessageViewModel.reactionsDoubleAttentionCount;
|
||||
reactionState = chatMessageViewModel.reactionsDoubleAttention;
|
||||
break;
|
||||
}
|
||||
case ReactionSymbols.Question: {
|
||||
audioLabel = translations.chatPage.message.questionReaction;
|
||||
audioLabel =
|
||||
coreViewModel.translations.chatPage.message.questionReaction;
|
||||
count = chatMessageViewModel.reactionsQuestionCount;
|
||||
reactionState = chatMessageViewModel.reactionsQuestion;
|
||||
break;
|
||||
|
||||
@@ -1,29 +1,42 @@
|
||||
import * as React from "bloatless-react";
|
||||
import { ReactionSymbols } from "../../Model/Chat/chatModel";
|
||||
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
|
||||
import { translations } from "../translations";
|
||||
import { MessageReactionButton } from "./messageReactionButton";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function MessageReactionButtonRow(
|
||||
coreViewModel: CoreViewModel,
|
||||
chatMessageViewModel: ChatMessageViewModel,
|
||||
) {
|
||||
return (
|
||||
<div class="grid gap width-100 message-reaction-row">
|
||||
{MessageReactionButton(
|
||||
coreViewModel,
|
||||
chatMessageViewModel,
|
||||
ReactionSymbols.ThumbsUp,
|
||||
)}
|
||||
{MessageReactionButton(chatMessageViewModel, ReactionSymbols.Check)}
|
||||
{MessageReactionButton(chatMessageViewModel, ReactionSymbols.Stop)}
|
||||
{MessageReactionButton(
|
||||
coreViewModel,
|
||||
chatMessageViewModel,
|
||||
ReactionSymbols.Check,
|
||||
)}
|
||||
{MessageReactionButton(
|
||||
coreViewModel,
|
||||
chatMessageViewModel,
|
||||
ReactionSymbols.Stop,
|
||||
)}
|
||||
{MessageReactionButton(
|
||||
coreViewModel,
|
||||
chatMessageViewModel,
|
||||
ReactionSymbols.Attention,
|
||||
)}
|
||||
{MessageReactionButton(
|
||||
coreViewModel,
|
||||
chatMessageViewModel,
|
||||
ReactionSymbols.DoubleAttention,
|
||||
)}
|
||||
{MessageReactionButton(
|
||||
coreViewModel,
|
||||
chatMessageViewModel,
|
||||
ReactionSymbols.Question,
|
||||
)}
|
||||
|
||||
@@ -3,11 +3,12 @@ import "./monthGrid.css";
|
||||
import * as React from "bloatless-react";
|
||||
import { MonthGrid } from "../../Model/Files/calendarModel";
|
||||
import TaskViewModel from "../../ViewModel/Pages/taskViewModel";
|
||||
import { translations } from "../translations";
|
||||
import { allowDrop } from "../utility";
|
||||
import { localeCompare } from "../../Model/Utility/utility";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function MonthGrid<T>(
|
||||
coreViewModel: CoreViewModel,
|
||||
monthGrid: MonthGrid<React.MapState<T>>,
|
||||
selectedDate: React.State<number>,
|
||||
handleDrop: (date: string) => void,
|
||||
@@ -17,7 +18,11 @@ export function MonthGrid<T>(
|
||||
while (dayLabels.length < 7) {
|
||||
dayLabels.push(
|
||||
<span class="secondary">
|
||||
{translations.regional.weekdays.abbreviated[currentWeekday]}
|
||||
{
|
||||
coreViewModel.translations.regional.weekdays.abbreviated[
|
||||
currentWeekday
|
||||
]
|
||||
}
|
||||
</span>,
|
||||
);
|
||||
currentWeekday++;
|
||||
|
||||
@@ -3,9 +3,12 @@ import * as React from "bloatless-react";
|
||||
import BoardViewModel from "../../ViewModel/Pages/boardViewModel";
|
||||
import { ColorPicker } from "../Components/colorPicker";
|
||||
import { DangerousActionButton } from "../Components/dangerousActionButton";
|
||||
import { translations } from "../translations";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function BoardSettingsModal(boardViewModel: BoardViewModel) {
|
||||
export function BoardSettingsModal(
|
||||
coreViewModel: CoreViewModel,
|
||||
boardViewModel: BoardViewModel,
|
||||
) {
|
||||
return (
|
||||
<div
|
||||
class="modal"
|
||||
@@ -13,13 +16,21 @@ export function BoardSettingsModal(boardViewModel: BoardViewModel) {
|
||||
>
|
||||
<div>
|
||||
<main>
|
||||
<h2>{translations.chatPage.task.boardSettingsHeadline}</h2>
|
||||
<h2>
|
||||
{
|
||||
coreViewModel.translations.chatPage.task
|
||||
.boardSettingsHeadline
|
||||
}
|
||||
</h2>
|
||||
|
||||
<label class="tile flex-no">
|
||||
<span class="icon">label</span>
|
||||
<div>
|
||||
<span>
|
||||
{translations.chatPage.task.boardNameInputLabel}
|
||||
{
|
||||
coreViewModel.translations.chatPage.task
|
||||
.boardNameInputLabel
|
||||
}
|
||||
</span>
|
||||
<input
|
||||
on:enter={boardViewModel.saveSettings}
|
||||
@@ -36,14 +47,16 @@ export function BoardSettingsModal(boardViewModel: BoardViewModel) {
|
||||
|
||||
<div class="width-input">
|
||||
{DangerousActionButton(
|
||||
translations.chatPage.task.deleteBoardButton,
|
||||
coreViewModel,
|
||||
coreViewModel.translations.chatPage.task
|
||||
.deleteBoardButton,
|
||||
"delete_forever",
|
||||
boardViewModel.deleteBoard,
|
||||
)}
|
||||
</div>
|
||||
</main>
|
||||
<button on:click={boardViewModel.hideSettings}>
|
||||
{translations.general.closeButton}
|
||||
{coreViewModel.translations.general.closeButton}
|
||||
<span class="icon">close</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import * as React from "bloatless-react";
|
||||
|
||||
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
|
||||
import { translations } from "../translations";
|
||||
import { MessageReactionButtonRow } from "../Components/messageReactionButtonRow";
|
||||
import { InfoTile } from "../Components/infoTile";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function ChatMessageInfoModal(
|
||||
coreViewModel: CoreViewModel,
|
||||
chatMessageViewModel: ChatMessageViewModel,
|
||||
) {
|
||||
return (
|
||||
@@ -15,27 +16,34 @@ export function ChatMessageInfoModal(
|
||||
>
|
||||
<div>
|
||||
<main>
|
||||
<h2>{translations.chatPage.message.messageInfoHeadline}</h2>
|
||||
<h2>
|
||||
{
|
||||
coreViewModel.translations.chatPage.message
|
||||
.messageInfoHeadline
|
||||
}
|
||||
</h2>
|
||||
|
||||
<div class="flex-column gap">
|
||||
{InfoTile(
|
||||
"account_circle",
|
||||
translations.chatPage.message.sentBy,
|
||||
coreViewModel.translations.chatPage.message.sentBy,
|
||||
chatMessageViewModel.sender,
|
||||
)}
|
||||
{InfoTile(
|
||||
"schedule",
|
||||
translations.chatPage.message.timeSent,
|
||||
coreViewModel.translations.chatPage.message
|
||||
.timeSent,
|
||||
chatMessageViewModel.dateSent,
|
||||
)}
|
||||
{InfoTile(
|
||||
"forum",
|
||||
translations.chatPage.message.channel,
|
||||
coreViewModel.translations.chatPage.message.channel,
|
||||
chatMessageViewModel.channel,
|
||||
)}
|
||||
{InfoTile(
|
||||
"description",
|
||||
translations.chatPage.message.messageContent,
|
||||
coreViewModel.translations.chatPage.message
|
||||
.messageContent,
|
||||
chatMessageViewModel.body,
|
||||
)}
|
||||
</div>
|
||||
@@ -44,25 +52,37 @@ export function ChatMessageInfoModal(
|
||||
|
||||
<div class="flex-column gap">
|
||||
<button on:click={chatMessageViewModel.copyMessage}>
|
||||
{translations.chatPage.message.copyMessageButton}
|
||||
{
|
||||
coreViewModel.translations.chatPage.message
|
||||
.copyMessageButton
|
||||
}
|
||||
<span class="icon">content_copy</span>
|
||||
</button>
|
||||
<button on:click={chatMessageViewModel.resendMessage}>
|
||||
{translations.chatPage.message.resendMessageButton}
|
||||
{
|
||||
coreViewModel.translations.chatPage.message
|
||||
.resendMessageButton
|
||||
}
|
||||
<span class="icon">redo</span>
|
||||
</button>
|
||||
<button on:click={chatMessageViewModel.decryptMessage}>
|
||||
{translations.chatPage.message.decryptMessageButton}
|
||||
{
|
||||
coreViewModel.translations.chatPage.message
|
||||
.decryptMessageButton
|
||||
}
|
||||
<span class="icon">key</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<hr></hr>
|
||||
|
||||
{MessageReactionButtonRow(chatMessageViewModel)}
|
||||
{MessageReactionButtonRow(
|
||||
coreViewModel,
|
||||
chatMessageViewModel,
|
||||
)}
|
||||
</main>
|
||||
<button on:click={chatMessageViewModel.hideInfoModal}>
|
||||
{translations.general.closeButton}
|
||||
{coreViewModel.translations.general.closeButton}
|
||||
<span class="icon">close</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -2,9 +2,12 @@ import * as React from "bloatless-react";
|
||||
|
||||
import ConnectionViewModel from "../../ViewModel/Global/connectionViewModel";
|
||||
import { DeletableListItem } from "../Components/deletableListItem";
|
||||
import { translations } from "../translations";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function ConnectionModal(connectionViewModel: ConnectionViewModel) {
|
||||
export function ConnectionModal(
|
||||
coreViewModel: CoreViewModel,
|
||||
connectionViewModel: ConnectionViewModel,
|
||||
) {
|
||||
const previousAddressConverter: React.StateItemConverter<string> = (
|
||||
address: string,
|
||||
) => {
|
||||
@@ -16,17 +19,20 @@ export function ConnectionModal(connectionViewModel: ConnectionViewModel) {
|
||||
[connectionViewModel.isConnected],
|
||||
() =>
|
||||
connectionViewModel.isConnected.value == true &&
|
||||
connectionViewModel.connectionModel.address == address,
|
||||
connectionViewModel.coreViewModel.connectionModel.address ==
|
||||
address,
|
||||
);
|
||||
|
||||
return DeletableListItem(
|
||||
coreViewModel,
|
||||
address,
|
||||
<button
|
||||
class="primary"
|
||||
on:click={connnect}
|
||||
toggle:disabled={cannotConnect}
|
||||
aria-label={
|
||||
translations.connectionModal.connectButtonAudioLabel
|
||||
coreViewModel.translations.connectionModal
|
||||
.connectButtonAudioLabel
|
||||
}
|
||||
>
|
||||
<span class="icon">link</span>
|
||||
@@ -45,7 +51,10 @@ export function ConnectionModal(connectionViewModel: ConnectionViewModel) {
|
||||
<div>
|
||||
<main>
|
||||
<h2>
|
||||
{translations.connectionModal.connectionModalHeadline}
|
||||
{
|
||||
coreViewModel.translations.connectionModal
|
||||
.connectionModalHeadline
|
||||
}
|
||||
</h2>
|
||||
|
||||
<div
|
||||
@@ -57,7 +66,7 @@ export function ConnectionModal(connectionViewModel: ConnectionViewModel) {
|
||||
></div>
|
||||
</main>
|
||||
<button on:click={connectionViewModel.hideConnectionModal}>
|
||||
{translations.general.closeButton}
|
||||
{coreViewModel.translations.general.closeButton}
|
||||
<span class="icon">close</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -9,28 +9,31 @@ import ConnectionViewModel from "../../ViewModel/Global/connectionViewModel";
|
||||
import StorageModel from "../../Model/Global/storageModel";
|
||||
import { StringToTextSpan } from "../Components/textSpan";
|
||||
import { reload } from "../utility";
|
||||
import { translations } from "../translations";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function DataTransferModalWrapper(
|
||||
coreViewModel: CoreViewModel,
|
||||
connectionViewModel: ConnectionViewModel,
|
||||
fileTransferViewModel: FileTransferViewModel,
|
||||
) {
|
||||
return (
|
||||
<div>
|
||||
{DirectionSelectionModal(
|
||||
coreViewModel,
|
||||
connectionViewModel,
|
||||
fileTransferViewModel,
|
||||
)}
|
||||
{FileSelectionModal(fileTransferViewModel)}
|
||||
{TransferDataDisplayModal(fileTransferViewModel)}
|
||||
{TransferDisplayModal(fileTransferViewModel)}
|
||||
{TransferDataInputModal(fileTransferViewModel)}
|
||||
{DataReceptionModal(fileTransferViewModel)}
|
||||
{FileSelectionModal(coreViewModel, fileTransferViewModel)}
|
||||
{TransferDataDisplayModal(coreViewModel, fileTransferViewModel)}
|
||||
{TransferDisplayModal(coreViewModel, fileTransferViewModel)}
|
||||
{TransferDataInputModal(coreViewModel, fileTransferViewModel)}
|
||||
{DataReceptionModal(coreViewModel, fileTransferViewModel)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function DirectionSelectionModal(
|
||||
coreViewModel: CoreViewModel,
|
||||
connectionViewModel: ConnectionViewModel,
|
||||
fileTransferViewModel: FileTransferViewModel,
|
||||
) {
|
||||
@@ -51,14 +54,20 @@ function DirectionSelectionModal(
|
||||
<div>
|
||||
<main>
|
||||
<h2>
|
||||
{translations.dataTransferModal.transferDataHeadline}
|
||||
{
|
||||
coreViewModel.translations.dataTransferModal
|
||||
.transferDataHeadline
|
||||
}
|
||||
</h2>
|
||||
|
||||
<p
|
||||
class="error"
|
||||
toggle:hidden={connectionViewModel.isConnected}
|
||||
>
|
||||
{translations.dataTransferModal.notConnectedError}
|
||||
{
|
||||
coreViewModel.translations.dataTransferModal
|
||||
.notConnectedError
|
||||
}
|
||||
</p>
|
||||
|
||||
<div
|
||||
@@ -75,7 +84,8 @@ function DirectionSelectionModal(
|
||||
<div>
|
||||
<b>
|
||||
{
|
||||
translations.dataTransferModal
|
||||
coreViewModel.translations
|
||||
.dataTransferModal
|
||||
.fromThisDeviceButton
|
||||
}
|
||||
</b>
|
||||
@@ -92,7 +102,8 @@ function DirectionSelectionModal(
|
||||
<div>
|
||||
<b>
|
||||
{
|
||||
translations.dataTransferModal
|
||||
coreViewModel.translations
|
||||
.dataTransferModal
|
||||
.toThisDeviceButton
|
||||
}
|
||||
</b>
|
||||
@@ -102,7 +113,7 @@ function DirectionSelectionModal(
|
||||
</div>
|
||||
</main>
|
||||
<button on:click={fileTransferViewModel.hideModal}>
|
||||
{translations.general.closeButton}
|
||||
{coreViewModel.translations.general.closeButton}
|
||||
<span class="icon">close</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -110,7 +121,10 @@ function DirectionSelectionModal(
|
||||
);
|
||||
}
|
||||
|
||||
function FileSelectionModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
function FileSelectionModal(
|
||||
coreViewModel: CoreViewModel,
|
||||
fileTransferViewModel: FileTransferViewModel,
|
||||
) {
|
||||
// option
|
||||
const OptionConverter: React.StateItemConverter<FileTransferOption> = (
|
||||
fileOption: FileTransferOption,
|
||||
@@ -164,15 +178,26 @@ function FileSelectionModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
<div>
|
||||
<main>
|
||||
<h2>
|
||||
{translations.dataTransferModal.transferDataHeadline}
|
||||
{
|
||||
coreViewModel.translations.dataTransferModal
|
||||
.transferDataHeadline
|
||||
}
|
||||
</h2>
|
||||
<span class="secondary">
|
||||
{translations.dataTransferModal.selectionDescription}
|
||||
{
|
||||
coreViewModel.translations.dataTransferModal
|
||||
.selectionDescription
|
||||
}
|
||||
</span>
|
||||
|
||||
<hr></hr>
|
||||
|
||||
<h3>{translations.dataTransferModal.generalHeadline}</h3>
|
||||
<h3>
|
||||
{
|
||||
coreViewModel.translations.dataTransferModal
|
||||
.generalHeadline
|
||||
}
|
||||
</h3>
|
||||
<div
|
||||
class="flex-column gap content-margin-bottom"
|
||||
children:append={[
|
||||
@@ -181,7 +206,12 @@ function FileSelectionModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
]}
|
||||
></div>
|
||||
|
||||
<h3>{translations.dataTransferModal.chatsHeadline}</h3>
|
||||
<h3>
|
||||
{
|
||||
coreViewModel.translations.dataTransferModal
|
||||
.chatsHeadline
|
||||
}
|
||||
</h3>
|
||||
<div
|
||||
class="flex-column gap"
|
||||
children:append={[
|
||||
@@ -197,7 +227,7 @@ function FileSelectionModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
fileTransferViewModel.showDirectionSelectionModal
|
||||
}
|
||||
>
|
||||
{translations.general.backButton}
|
||||
{coreViewModel.translations.general.backButton}
|
||||
</button>
|
||||
<button
|
||||
class="primary flex"
|
||||
@@ -206,7 +236,7 @@ function FileSelectionModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
fileTransferViewModel.hasNoPathsSelected
|
||||
}
|
||||
>
|
||||
{translations.general.continueButton}
|
||||
{coreViewModel.translations.general.continueButton}
|
||||
<span class="icon">arrow_forward</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -216,6 +246,7 @@ function FileSelectionModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
}
|
||||
|
||||
function TransferDataDisplayModal(
|
||||
coreViewModel: CoreViewModel,
|
||||
fileTransferViewModel: FileTransferViewModel,
|
||||
) {
|
||||
const isPresented = React.createProxyState(
|
||||
@@ -230,11 +261,17 @@ function TransferDataDisplayModal(
|
||||
<div>
|
||||
<main>
|
||||
<h2>
|
||||
{translations.dataTransferModal.transferDataHeadline}
|
||||
{
|
||||
coreViewModel.translations.dataTransferModal
|
||||
.transferDataHeadline
|
||||
}
|
||||
</h2>
|
||||
|
||||
<span class="secondary">
|
||||
{translations.dataTransferModal.dataEntryDescription}
|
||||
{
|
||||
coreViewModel.translations.dataTransferModal
|
||||
.dataEntryDescription
|
||||
}
|
||||
</span>
|
||||
|
||||
<hr></hr>
|
||||
@@ -245,7 +282,8 @@ function TransferDataDisplayModal(
|
||||
<div>
|
||||
<span class="secondary">
|
||||
{
|
||||
translations.dataTransferModal
|
||||
coreViewModel.translations
|
||||
.dataTransferModal
|
||||
.transferChannelHeadline
|
||||
}
|
||||
</span>
|
||||
@@ -261,7 +299,8 @@ function TransferDataDisplayModal(
|
||||
<div>
|
||||
<span class="secondary">
|
||||
{
|
||||
translations.dataTransferModal
|
||||
coreViewModel.translations
|
||||
.dataTransferModal
|
||||
.transferKeyHeadline
|
||||
}
|
||||
</span>
|
||||
@@ -279,10 +318,10 @@ function TransferDataDisplayModal(
|
||||
class="flex"
|
||||
on:click={fileTransferViewModel.showFileSelectionModal}
|
||||
>
|
||||
{translations.general.backButton}
|
||||
{coreViewModel.translations.general.backButton}
|
||||
</button>
|
||||
<button disabled class="flex">
|
||||
{translations.general.waitingLabel}
|
||||
{coreViewModel.translations.general.waitingLabel}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -290,7 +329,10 @@ function TransferDataDisplayModal(
|
||||
);
|
||||
}
|
||||
|
||||
function TransferDisplayModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
function TransferDisplayModal(
|
||||
coreViewModel: CoreViewModel,
|
||||
fileTransferViewModel: FileTransferViewModel,
|
||||
) {
|
||||
const isPresented = React.createProxyState(
|
||||
[fileTransferViewModel.presentedModal],
|
||||
() =>
|
||||
@@ -303,7 +345,10 @@ function TransferDisplayModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
<div>
|
||||
<main>
|
||||
<h2>
|
||||
{translations.dataTransferModal.transferDataHeadline}
|
||||
{
|
||||
coreViewModel.translations.dataTransferModal
|
||||
.transferDataHeadline
|
||||
}
|
||||
</h2>
|
||||
|
||||
<p
|
||||
@@ -319,7 +364,10 @@ function TransferDisplayModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
fileTransferViewModel.didNotFinishSending
|
||||
}
|
||||
>
|
||||
{translations.dataTransferModal.allFilesSent}
|
||||
{
|
||||
coreViewModel.translations.dataTransferModal
|
||||
.allFilesSent
|
||||
}
|
||||
</p>
|
||||
|
||||
<hr></hr>
|
||||
@@ -337,7 +385,10 @@ function TransferDisplayModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
class="flex"
|
||||
on:click={fileTransferViewModel.initiateTransfer}
|
||||
>
|
||||
{translations.dataTransferModal.sendAgainButton}
|
||||
{
|
||||
coreViewModel.translations.dataTransferModal
|
||||
.sendAgainButton
|
||||
}
|
||||
<span class="icon">restart_alt</span>
|
||||
</button>
|
||||
<button
|
||||
@@ -347,7 +398,7 @@ function TransferDisplayModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
fileTransferViewModel.didNotFinishSending
|
||||
}
|
||||
>
|
||||
{translations.general.closeButton}
|
||||
{coreViewModel.translations.general.closeButton}
|
||||
<span class="icon">close</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -356,7 +407,10 @@ function TransferDisplayModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
);
|
||||
}
|
||||
|
||||
function TransferDataInputModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
function TransferDataInputModal(
|
||||
coreViewModel: CoreViewModel,
|
||||
fileTransferViewModel: FileTransferViewModel,
|
||||
) {
|
||||
const isPresented = React.createProxyState(
|
||||
[fileTransferViewModel.presentedModal],
|
||||
() =>
|
||||
@@ -369,12 +423,15 @@ function TransferDataInputModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
<div>
|
||||
<main>
|
||||
<h2>
|
||||
{translations.dataTransferModal.transferDataHeadline}
|
||||
{
|
||||
coreViewModel.translations.dataTransferModal
|
||||
.transferDataHeadline
|
||||
}
|
||||
</h2>
|
||||
|
||||
<span class="secondary">
|
||||
{
|
||||
translations.dataTransferModal
|
||||
coreViewModel.translations.dataTransferModal
|
||||
.dataEntryInputDescription
|
||||
}
|
||||
</span>
|
||||
@@ -387,7 +444,8 @@ function TransferDataInputModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
<div>
|
||||
<span class="secondary">
|
||||
{
|
||||
translations.dataTransferModal
|
||||
coreViewModel.translations
|
||||
.dataTransferModal
|
||||
.transferChannelHeadline
|
||||
}
|
||||
</span>
|
||||
@@ -403,7 +461,8 @@ function TransferDataInputModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
<div>
|
||||
<span class="secondary">
|
||||
{
|
||||
translations.dataTransferModal
|
||||
coreViewModel.translations
|
||||
.dataTransferModal
|
||||
.transferKeyHeadline
|
||||
}
|
||||
</span>
|
||||
@@ -423,7 +482,7 @@ function TransferDataInputModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
fileTransferViewModel.showDirectionSelectionModal
|
||||
}
|
||||
>
|
||||
{translations.general.backButton}
|
||||
{coreViewModel.translations.general.backButton}
|
||||
</button>
|
||||
<button
|
||||
class="primary flex"
|
||||
@@ -432,7 +491,7 @@ function TransferDataInputModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
fileTransferViewModel.cannotPrepareToReceive
|
||||
}
|
||||
>
|
||||
{translations.general.continueButton}
|
||||
{coreViewModel.translations.general.continueButton}
|
||||
<span class="icon">arrow_forward</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -441,7 +500,10 @@ function TransferDataInputModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
);
|
||||
}
|
||||
|
||||
function DataReceptionModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
function DataReceptionModal(
|
||||
coreViewModel: CoreViewModel,
|
||||
fileTransferViewModel: FileTransferViewModel,
|
||||
) {
|
||||
const isPresented = React.createProxyState(
|
||||
[fileTransferViewModel.presentedModal],
|
||||
() =>
|
||||
@@ -454,7 +516,10 @@ function DataReceptionModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
<div>
|
||||
<main>
|
||||
<h2>
|
||||
{translations.dataTransferModal.transferDataHeadline}
|
||||
{
|
||||
coreViewModel.translations.dataTransferModal
|
||||
.transferDataHeadline
|
||||
}
|
||||
</h2>
|
||||
|
||||
<p
|
||||
@@ -475,7 +540,7 @@ function DataReceptionModal(fileTransferViewModel: FileTransferViewModel) {
|
||||
></div>
|
||||
</main>
|
||||
<button on:click={reload}>
|
||||
{translations.general.reloadAppButton}
|
||||
{coreViewModel.translations.general.reloadAppButton}
|
||||
<span class="icon">refresh</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -2,10 +2,11 @@ import * as React from "bloatless-react";
|
||||
|
||||
import SearchViewModel from "../../ViewModel/Utility/searchViewModel";
|
||||
import { StringToOption } from "../Components/option";
|
||||
import { translations } from "../translations";
|
||||
import { v4 } from "uuid";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function SearchModal<T>(
|
||||
coreViewModel: CoreViewModel,
|
||||
searchViewModel: SearchViewModel<T>,
|
||||
headline: string,
|
||||
converter: React.StateItemConverter<T>,
|
||||
@@ -24,7 +25,9 @@ export function SearchModal<T>(
|
||||
<h2>{headline}</h2>
|
||||
<div class="flex-row width-input">
|
||||
<input
|
||||
placeholder={translations.general.searchLabel}
|
||||
placeholder={
|
||||
coreViewModel.translations.general.searchLabel
|
||||
}
|
||||
bind:value={searchViewModel.searchInput}
|
||||
on:enter={searchViewModel.applySearch}
|
||||
list={suggestionId}
|
||||
@@ -40,7 +43,8 @@ export function SearchModal<T>(
|
||||
<button
|
||||
class="primary"
|
||||
aria-label={
|
||||
translations.general.searchButtonAudioLabel
|
||||
coreViewModel.translations.general
|
||||
.searchButtonAudioLabel
|
||||
}
|
||||
on:click={searchViewModel.applySearch}
|
||||
toggle:disabled={searchViewModel.cannotApplySearch}
|
||||
@@ -61,7 +65,7 @@ export function SearchModal<T>(
|
||||
></div>
|
||||
</main>
|
||||
<button on:click={close}>
|
||||
{translations.general.closeButton}
|
||||
{coreViewModel.translations.general.closeButton}
|
||||
<span class="icon">close</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
import * as React from "bloatless-react";
|
||||
|
||||
import { translations } from "../translations";
|
||||
import { Languages } from "../translations";
|
||||
import SettingsViewModel, {
|
||||
SettingsModalPages,
|
||||
} from "../../ViewModel/Global/settingsViewModel";
|
||||
import { SplitModal } from "../Components/splitModal";
|
||||
import { InfoTile } from "../Components/infoTile";
|
||||
import { Option } from "../Components/option";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function SettingsModal(settingsViewModel: SettingsViewModel) {
|
||||
export function SettingsModal(
|
||||
coreViewModel: CoreViewModel,
|
||||
settingsViewModel: SettingsViewModel,
|
||||
) {
|
||||
const detailView = React.createProxyState(
|
||||
[settingsViewModel.selectedModalPage],
|
||||
() => {
|
||||
@@ -16,9 +20,12 @@ export function SettingsModal(settingsViewModel: SettingsViewModel) {
|
||||
case SettingsModalPages.Appearance:
|
||||
return <div>Appearance</div>;
|
||||
case SettingsModalPages.Regional:
|
||||
return SettingsRegionalPane(settingsViewModel);
|
||||
return SettingsRegionalPane(
|
||||
coreViewModel,
|
||||
settingsViewModel,
|
||||
);
|
||||
case SettingsModalPages.Info:
|
||||
return SettingsInfoPane(settingsViewModel);
|
||||
return SettingsInfoPane(coreViewModel, settingsViewModel);
|
||||
}
|
||||
},
|
||||
);
|
||||
@@ -31,7 +38,9 @@ export function SettingsModal(settingsViewModel: SettingsViewModel) {
|
||||
<div>
|
||||
<main class="padding-0">
|
||||
{SplitModal(
|
||||
new React.State(SettingsLeftPane(settingsViewModel)),
|
||||
new React.State(
|
||||
SettingsLeftPane(coreViewModel, settingsViewModel),
|
||||
),
|
||||
detailView,
|
||||
new React.State(""),
|
||||
false,
|
||||
@@ -39,7 +48,7 @@ export function SettingsModal(settingsViewModel: SettingsViewModel) {
|
||||
)}
|
||||
</main>
|
||||
<button on:click={settingsViewModel.hideSettingsModal}>
|
||||
{translations.general.closeButton}
|
||||
{coreViewModel.translations.general.closeButton}
|
||||
<span class="icon">close</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -47,23 +56,26 @@ export function SettingsModal(settingsViewModel: SettingsViewModel) {
|
||||
);
|
||||
}
|
||||
|
||||
function SettingsLeftPane(settingsViewModel: SettingsViewModel) {
|
||||
function SettingsLeftPane(
|
||||
coreViewModel: CoreViewModel,
|
||||
settingsViewModel: SettingsViewModel,
|
||||
) {
|
||||
return (
|
||||
<div class="flex-column gap">
|
||||
{SettingsPaneButton(
|
||||
settingsViewModel,
|
||||
SettingsModalPages.Appearance,
|
||||
translations.settings.pages.appearance,
|
||||
coreViewModel.translations.settings.pages.appearance,
|
||||
)}
|
||||
{SettingsPaneButton(
|
||||
settingsViewModel,
|
||||
SettingsModalPages.Regional,
|
||||
translations.settings.pages.regional,
|
||||
coreViewModel.translations.settings.pages.regional,
|
||||
)}
|
||||
{SettingsPaneButton(
|
||||
settingsViewModel,
|
||||
SettingsModalPages.Info,
|
||||
translations.settings.pages.info,
|
||||
coreViewModel.translations.settings.pages.info,
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
@@ -89,15 +101,18 @@ function SettingsPaneButton(
|
||||
);
|
||||
}
|
||||
|
||||
function SettingsInfoPane(settingsViewModel: SettingsViewModel) {
|
||||
function SettingsInfoPane(
|
||||
coreViewModel: CoreViewModel,
|
||||
settingsViewModel: SettingsViewModel,
|
||||
) {
|
||||
return (
|
||||
<div class="slide-up">
|
||||
<h2>{translations.homePage.appName}</h2>
|
||||
<h2>{coreViewModel.translations.homePage.appName}</h2>
|
||||
<hr></hr>
|
||||
<div class="flex-column gap">
|
||||
{InfoTile(
|
||||
"build",
|
||||
translations.settings.version,
|
||||
coreViewModel.translations.settings.version,
|
||||
settingsViewModel.coreViewModel.BUILD,
|
||||
)}
|
||||
</div>
|
||||
@@ -105,30 +120,54 @@ function SettingsInfoPane(settingsViewModel: SettingsViewModel) {
|
||||
);
|
||||
}
|
||||
|
||||
function SettingsRegionalPane(settingsViewModel: SettingsViewModel) {
|
||||
function SettingsRegionalPane(
|
||||
coreViewModel: CoreViewModel,
|
||||
settingsViewModel: SettingsViewModel,
|
||||
) {
|
||||
return (
|
||||
<div class="slide-up">
|
||||
<h2>{translations.settings.pages.regional}</h2>
|
||||
<h2>{coreViewModel.translations.settings.pages.regional}</h2>
|
||||
<hr></hr>
|
||||
<label class="tile flex-no">
|
||||
<span class="icon">calendar_month</span>
|
||||
<div>
|
||||
<span>{translations.homePage.firstDayOfWeekLabel}</span>
|
||||
<select bind:value={settingsViewModel.firstDayOfWeekInput}>
|
||||
{...translations.regional.weekdays.full.map(
|
||||
<span>
|
||||
{
|
||||
coreViewModel.translations.settings
|
||||
.firstDayOfWeekLabel
|
||||
}
|
||||
</span>
|
||||
<select bind:value={settingsViewModel.firstDayOfWeek}>
|
||||
{...coreViewModel.translations.regional.weekdays.full.map(
|
||||
(weekdayName, i) =>
|
||||
Option(
|
||||
weekdayName,
|
||||
i.toString(),
|
||||
i.toString() ==
|
||||
settingsViewModel.firstDayOfWeekInput
|
||||
.value,
|
||||
settingsViewModel.firstDayOfWeek.value,
|
||||
),
|
||||
)}
|
||||
</select>
|
||||
<span class="icon">arrow_drop_down</span>
|
||||
</div>
|
||||
</label>
|
||||
<label class="tile flex-no">
|
||||
<span class="icon">language</span>
|
||||
<div>
|
||||
<span>{coreViewModel.translations.settings.language}</span>
|
||||
<select bind:value={settingsViewModel.language}>
|
||||
{...[...Object.values(Languages)].map((language, i) =>
|
||||
Option(
|
||||
language,
|
||||
i.toString(),
|
||||
i.toString() ==
|
||||
settingsViewModel.language.value,
|
||||
),
|
||||
)}
|
||||
</select>
|
||||
<span class="icon">arrow_drop_down</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,13 +2,16 @@ import * as React from "bloatless-react";
|
||||
|
||||
import { PATH_COMPONENT_SEPARATOR } from "../../Model/Global/storageModel";
|
||||
import StorageViewModel from "../../ViewModel/Global/storageViewModel";
|
||||
import { translations } from "../translations";
|
||||
|
||||
import { SplitModal } from "../Components/splitModal";
|
||||
import { DangerousActionButton } from "../Components/dangerousActionButton";
|
||||
import { DirectoryItemList } from "../Components/directoryItemList";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function StorageModal(storageViewModel: StorageViewModel) {
|
||||
export function StorageModal(
|
||||
coreViewModel: CoreViewModel,
|
||||
storageViewModel: StorageViewModel,
|
||||
) {
|
||||
const detailView = React.createProxyState(
|
||||
[storageViewModel.selectedPath],
|
||||
() => {
|
||||
@@ -16,13 +19,14 @@ export function StorageModal(storageViewModel: StorageViewModel) {
|
||||
return (
|
||||
<div>
|
||||
<span class="secondary">
|
||||
{translations.storage.noItemSelected}
|
||||
{coreViewModel.translations.storage.noItemSelected}
|
||||
</span>
|
||||
|
||||
<hr></hr>
|
||||
|
||||
{DangerousActionButton(
|
||||
translations.storage.removeJunkButton,
|
||||
coreViewModel,
|
||||
coreViewModel.translations.storage.removeJunkButton,
|
||||
"delete_forever",
|
||||
storageViewModel.removeJunk,
|
||||
)}
|
||||
@@ -33,7 +37,7 @@ export function StorageModal(storageViewModel: StorageViewModel) {
|
||||
<div class="flex-column gap">
|
||||
<div class="tile flex-no">
|
||||
<div>
|
||||
<b>{translations.storage.path}</b>
|
||||
<b>{coreViewModel.translations.storage.path}</b>
|
||||
<span
|
||||
class="break-all"
|
||||
subscribe:innerText={
|
||||
@@ -44,7 +48,7 @@ export function StorageModal(storageViewModel: StorageViewModel) {
|
||||
</div>
|
||||
<div class="tile flex-no">
|
||||
<div>
|
||||
<b>{translations.storage.content}</b>
|
||||
<b>{coreViewModel.translations.storage.content}</b>
|
||||
<code
|
||||
subscribe:innerText={
|
||||
storageViewModel.selectedFileContent
|
||||
@@ -54,7 +58,8 @@ export function StorageModal(storageViewModel: StorageViewModel) {
|
||||
</div>
|
||||
|
||||
{DangerousActionButton(
|
||||
translations.storage.deleteItem,
|
||||
coreViewModel,
|
||||
coreViewModel.translations.storage.deleteItem,
|
||||
"delete_forever",
|
||||
storageViewModel.deleteSelectedItem,
|
||||
)}
|
||||
@@ -74,7 +79,7 @@ export function StorageModal(storageViewModel: StorageViewModel) {
|
||||
)}
|
||||
</main>
|
||||
<button on:click={storageViewModel.hideStorageModal}>
|
||||
{translations.general.closeButton}
|
||||
{coreViewModel.translations.general.closeButton}
|
||||
<span class="icon">close</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,6 @@ import * as React from "bloatless-react";
|
||||
|
||||
import {
|
||||
Entry,
|
||||
EntryToOption,
|
||||
Option,
|
||||
StringToOption,
|
||||
VersionIdToOption,
|
||||
@@ -10,10 +9,13 @@ import {
|
||||
|
||||
import { DangerousActionButton } from "../Components/dangerousActionButton";
|
||||
import TaskViewModel from "../../ViewModel/Pages/taskViewModel";
|
||||
import { translations } from "../translations";
|
||||
import { v4 } from "uuid";
|
||||
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function TaskSettingsModal(taskViewModel: TaskViewModel) {
|
||||
export function TaskSettingsModal(
|
||||
coreViewModel: CoreViewModel,
|
||||
taskViewModel: TaskViewModel,
|
||||
) {
|
||||
const categorySuggestionId = v4();
|
||||
const statusSuggestionId = v4();
|
||||
|
||||
@@ -28,12 +30,22 @@ export function TaskSettingsModal(taskViewModel: TaskViewModel) {
|
||||
<div class="modal" open keystroke:s={taskViewModel.closeAndSave}>
|
||||
<div>
|
||||
<main>
|
||||
<h2>{translations.chatPage.task.taskSettingsHeadline}</h2>
|
||||
<h2>
|
||||
{
|
||||
coreViewModel.translations.chatPage.task
|
||||
.taskSettingsHeadline
|
||||
}
|
||||
</h2>
|
||||
|
||||
<label class="tile flex-no">
|
||||
<span class="icon">history</span>
|
||||
<div>
|
||||
<span>{translations.general.fileVersionLabel}</span>
|
||||
<span>
|
||||
{
|
||||
coreViewModel.translations.general
|
||||
.fileVersionLabel
|
||||
}
|
||||
</span>
|
||||
<select
|
||||
bind:value={taskViewModel.selectedVersionId}
|
||||
children:append={[
|
||||
@@ -51,7 +63,10 @@ export function TaskSettingsModal(taskViewModel: TaskViewModel) {
|
||||
<span class="icon">label</span>
|
||||
<div>
|
||||
<span>
|
||||
{translations.chatPage.task.taskNameLabel}
|
||||
{
|
||||
coreViewModel.translations.chatPage.task
|
||||
.taskNameLabel
|
||||
}
|
||||
</span>
|
||||
<input
|
||||
bind:value={taskViewModel.name}
|
||||
@@ -64,7 +79,10 @@ export function TaskSettingsModal(taskViewModel: TaskViewModel) {
|
||||
<span class="icon">category</span>
|
||||
<div>
|
||||
<span>
|
||||
{translations.chatPage.task.taskBoardLabel}
|
||||
{
|
||||
coreViewModel.translations.chatPage.task
|
||||
.taskBoardLabel
|
||||
}
|
||||
</span>
|
||||
<select
|
||||
bind:value={taskViewModel.boardId}
|
||||
@@ -83,7 +101,7 @@ export function TaskSettingsModal(taskViewModel: TaskViewModel) {
|
||||
<div>
|
||||
<span>
|
||||
{
|
||||
translations.chatPage.task
|
||||
coreViewModel.translations.chatPage.task
|
||||
.taskDescriptionLabel
|
||||
}
|
||||
</span>
|
||||
@@ -100,7 +118,10 @@ export function TaskSettingsModal(taskViewModel: TaskViewModel) {
|
||||
<span class="icon">category</span>
|
||||
<div>
|
||||
<span>
|
||||
{translations.chatPage.task.taskCategoryLabel}
|
||||
{
|
||||
coreViewModel.translations.chatPage.task
|
||||
.taskCategoryLabel
|
||||
}
|
||||
</span>
|
||||
<input
|
||||
bind:value={taskViewModel.category}
|
||||
@@ -121,7 +142,10 @@ export function TaskSettingsModal(taskViewModel: TaskViewModel) {
|
||||
<span class="icon">clock_loader_40</span>
|
||||
<div>
|
||||
<span>
|
||||
{translations.chatPage.task.taskStatusLabel}
|
||||
{
|
||||
coreViewModel.translations.chatPage.task
|
||||
.taskStatusLabel
|
||||
}
|
||||
</span>
|
||||
<input
|
||||
bind:value={taskViewModel.status}
|
||||
@@ -142,7 +166,10 @@ export function TaskSettingsModal(taskViewModel: TaskViewModel) {
|
||||
<span class="icon">priority_high</span>
|
||||
<div>
|
||||
<span>
|
||||
{translations.chatPage.task.taskPriorityLabel}
|
||||
{
|
||||
coreViewModel.translations.chatPage.task
|
||||
.taskPriorityLabel
|
||||
}
|
||||
</span>
|
||||
<input
|
||||
type="number"
|
||||
@@ -157,7 +184,10 @@ export function TaskSettingsModal(taskViewModel: TaskViewModel) {
|
||||
<span class="icon">calendar_month</span>
|
||||
<div>
|
||||
<span>
|
||||
{translations.chatPage.task.taskDateLabel}
|
||||
{
|
||||
coreViewModel.translations.chatPage.task
|
||||
.taskDateLabel
|
||||
}
|
||||
</span>
|
||||
<input
|
||||
type="date"
|
||||
@@ -170,7 +200,10 @@ export function TaskSettingsModal(taskViewModel: TaskViewModel) {
|
||||
<span class="icon">schedule</span>
|
||||
<div>
|
||||
<span>
|
||||
{translations.chatPage.task.taskTimeLabel}
|
||||
{
|
||||
coreViewModel.translations.chatPage.task
|
||||
.taskTimeLabel
|
||||
}
|
||||
</span>
|
||||
<input
|
||||
type="time"
|
||||
@@ -183,7 +216,9 @@ export function TaskSettingsModal(taskViewModel: TaskViewModel) {
|
||||
|
||||
<div class="width-input">
|
||||
{DangerousActionButton(
|
||||
translations.chatPage.task.deleteTaskButton,
|
||||
coreViewModel,
|
||||
coreViewModel.translations.chatPage.task
|
||||
.deleteTaskButton,
|
||||
"delete_forever",
|
||||
taskViewModel.deleteTask,
|
||||
)}
|
||||
@@ -194,13 +229,13 @@ export function TaskSettingsModal(taskViewModel: TaskViewModel) {
|
||||
class="flex"
|
||||
on:click={taskViewModel.closeAndDiscard}
|
||||
>
|
||||
{translations.general.closeButton}
|
||||
{coreViewModel.translations.general.closeButton}
|
||||
</button>
|
||||
<button
|
||||
class="flex primary"
|
||||
on:click={taskViewModel.closeAndSave}
|
||||
>
|
||||
{translations.general.saveButton}
|
||||
{coreViewModel.translations.general.saveButton}
|
||||
<span class="icon">save</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
+32
-12
@@ -9,9 +9,12 @@ import { ChatViewToggleButton } from "./Components/chatViewToggleButton";
|
||||
import { MessagePage } from "./ChatPages/messagePage";
|
||||
import { SettingsPage } from "./ChatPages/settingsPage";
|
||||
import { TaskPage } from "./ChatPages/taskPage";
|
||||
import { translations } from "./translations";
|
||||
import CoreViewModel from "../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function ChatPage(chatViewModel: ChatViewModel) {
|
||||
export function ChatPage(
|
||||
coreViewModel: CoreViewModel,
|
||||
chatViewModel: ChatViewModel,
|
||||
) {
|
||||
const mainContent = React.createProxyState(
|
||||
[chatViewModel.selectedPage],
|
||||
() => {
|
||||
@@ -19,16 +22,28 @@ export function ChatPage(chatViewModel: ChatViewModel) {
|
||||
|
||||
switch (chatViewModel.selectedPage.value) {
|
||||
case ChatPageTypes.Settings: {
|
||||
return SettingsPage(chatViewModel.settingsPageViewModel);
|
||||
return SettingsPage(
|
||||
coreViewModel,
|
||||
chatViewModel.settingsPageViewModel,
|
||||
);
|
||||
}
|
||||
case ChatPageTypes.Tasks: {
|
||||
return TaskPage(chatViewModel.taskPageViewModel);
|
||||
return TaskPage(
|
||||
coreViewModel,
|
||||
chatViewModel.taskPageViewModel,
|
||||
);
|
||||
}
|
||||
case ChatPageTypes.Calendar: {
|
||||
return CalendarPage(chatViewModel.calendarViewModel);
|
||||
return CalendarPage(
|
||||
coreViewModel,
|
||||
chatViewModel.calendarViewModel,
|
||||
);
|
||||
}
|
||||
default: {
|
||||
return MessagePage(chatViewModel.messagePageViewModel);
|
||||
return MessagePage(
|
||||
coreViewModel,
|
||||
chatViewModel.messagePageViewModel,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -63,14 +78,19 @@ export function ChatPage(chatViewModel: ChatViewModel) {
|
||||
<div id="ribbon">
|
||||
<button
|
||||
class="ghost"
|
||||
aria-label={translations.chatPage.closeChatAudioLabe}
|
||||
aria-label={
|
||||
coreViewModel.translations.chatPage
|
||||
.closeChatAudioLabe
|
||||
}
|
||||
on:click={chatViewModel.close}
|
||||
>
|
||||
<span class="icon">close</span>
|
||||
</button>
|
||||
<button
|
||||
class="danger"
|
||||
aria-label={translations.general.restoreConnection}
|
||||
aria-label={
|
||||
coreViewModel.translations.general.restoreConnection
|
||||
}
|
||||
on:click={
|
||||
chatViewModel.connectionViewModel
|
||||
.showConnectionModal
|
||||
@@ -86,25 +106,25 @@ export function ChatPage(chatViewModel: ChatViewModel) {
|
||||
|
||||
<span class="navigation-buttons">
|
||||
{ChatViewToggleButton(
|
||||
translations.chatPage.pages.calendar,
|
||||
coreViewModel.translations.chatPage.pages.calendar,
|
||||
"calendar_month",
|
||||
ChatPageTypes.Calendar,
|
||||
chatViewModel,
|
||||
)}
|
||||
{ChatViewToggleButton(
|
||||
translations.chatPage.pages.tasks,
|
||||
coreViewModel.translations.chatPage.pages.tasks,
|
||||
"task_alt",
|
||||
ChatPageTypes.Tasks,
|
||||
chatViewModel,
|
||||
)}
|
||||
{ChatViewToggleButton(
|
||||
translations.chatPage.pages.messages,
|
||||
coreViewModel.translations.chatPage.pages.messages,
|
||||
"forum",
|
||||
ChatPageTypes.Messages,
|
||||
chatViewModel,
|
||||
)}
|
||||
{ChatViewToggleButton(
|
||||
translations.chatPage.pages.settings,
|
||||
coreViewModel.translations.chatPage.pages.settings,
|
||||
"settings",
|
||||
ChatPageTypes.Settings,
|
||||
chatViewModel,
|
||||
|
||||
@@ -4,15 +4,22 @@ import * as React from "bloatless-react";
|
||||
|
||||
import ChatListViewModel from "../ViewModel/Chat/chatListViewModel";
|
||||
import { ChatPage } from "./chatPage";
|
||||
import CoreViewModel from "../ViewModel/Global/coreViewModel";
|
||||
|
||||
export function ChatPageWrapper(chatListViewModel: ChatListViewModel) {
|
||||
export function ChatPageWrapper(
|
||||
coreViewModel: CoreViewModel,
|
||||
chatListViewModel: ChatListViewModel,
|
||||
) {
|
||||
const chatPageContent = React.createProxyState(
|
||||
[chatListViewModel.selectedChat],
|
||||
() => {
|
||||
if (chatListViewModel.selectedChat.value == undefined) {
|
||||
return <div></div>;
|
||||
} else {
|
||||
return ChatPage(chatListViewModel.selectedChat.value);
|
||||
return ChatPage(
|
||||
coreViewModel,
|
||||
chatListViewModel.selectedChat.value,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
+41
-20
@@ -10,12 +10,11 @@ import ConnectionViewModel from "../ViewModel/Global/connectionViewModel";
|
||||
import FileTransferViewModel from "../ViewModel/Global/fileTransferViewModel";
|
||||
import SettingsViewModel from "../ViewModel/Global/settingsViewModel";
|
||||
import StorageViewModel from "../ViewModel/Global/storageViewModel";
|
||||
import { translations } from "./translations";
|
||||
import CoreViewModel from "../ViewModel/Global/coreViewModel";
|
||||
import { HomePageButton } from "./Components/homePageButton";
|
||||
|
||||
export function HomePage(
|
||||
coreVieWModel: CoreViewModel,
|
||||
coreViewModel: CoreViewModel,
|
||||
storageViewModel: StorageViewModel,
|
||||
settingsViewModel: SettingsViewModel,
|
||||
connectionViewModel: ConnectionViewModel,
|
||||
@@ -25,16 +24,19 @@ export function HomePage(
|
||||
// sections
|
||||
const overviewSection = (
|
||||
<div id="overview-section">
|
||||
<h2>{translations.homePage.overviewHeadline}</h2>
|
||||
<h2>{coreViewModel.translations.homePage.overviewHeadline}</h2>
|
||||
|
||||
<label class="tile flex-no">
|
||||
<span class="icon">cell_tower</span>
|
||||
<div>
|
||||
<span>{translations.homePage.serverAddress}</span>
|
||||
<span>
|
||||
{coreViewModel.translations.homePage.serverAddress}
|
||||
</span>
|
||||
<input
|
||||
list="previous-connection-list"
|
||||
placeholder={
|
||||
translations.homePage.serverAddressPlaceholder
|
||||
coreViewModel.translations.homePage
|
||||
.serverAddressPlaceholder
|
||||
}
|
||||
bind:value={connectionViewModel.serverAddressInput}
|
||||
on:enter={connectionViewModel.connect}
|
||||
@@ -53,7 +55,9 @@ export function HomePage(
|
||||
<div class="flex-row">
|
||||
<button
|
||||
class="danger flex justify-center"
|
||||
aria-label={translations.homePage.disconnectAudioLabel}
|
||||
aria-label={
|
||||
coreViewModel.translations.homePage.disconnectAudioLabel
|
||||
}
|
||||
on:click={connectionViewModel.disconnect}
|
||||
toggle:disabled={connectionViewModel.cannotDisonnect}
|
||||
>
|
||||
@@ -62,7 +66,8 @@ export function HomePage(
|
||||
<button
|
||||
class="flex justify-center"
|
||||
aria-label={
|
||||
translations.homePage.manageConnectionsAudioLabel
|
||||
coreViewModel.translations.homePage
|
||||
.manageConnectionsAudioLabel
|
||||
}
|
||||
on:click={connectionViewModel.showConnectionModal}
|
||||
toggle:disabled={
|
||||
@@ -73,7 +78,9 @@ export function HomePage(
|
||||
</button>
|
||||
<button
|
||||
class="primary flex justify-center"
|
||||
aria-label={translations.homePage.connectAudioLabel}
|
||||
aria-label={
|
||||
coreViewModel.translations.homePage.connectAudioLabel
|
||||
}
|
||||
on:click={connectionViewModel.connect}
|
||||
toggle:disabled={connectionViewModel.cannotConnect}
|
||||
>
|
||||
@@ -86,9 +93,14 @@ export function HomePage(
|
||||
<label class="tile flex-no">
|
||||
<span class="icon">account_circle</span>
|
||||
<div>
|
||||
<span>{translations.homePage.yourNameLabel}</span>
|
||||
<span>
|
||||
{coreViewModel.translations.homePage.yourNameLabel}
|
||||
</span>
|
||||
<input
|
||||
placeholder={translations.homePage.yourNamePlaceholder}
|
||||
placeholder={
|
||||
coreViewModel.translations.homePage
|
||||
.yourNamePlaceholder
|
||||
}
|
||||
bind:value={settingsViewModel.usernameInput}
|
||||
on:enter={settingsViewModel.setName}
|
||||
></input>
|
||||
@@ -99,9 +111,12 @@ export function HomePage(
|
||||
class="width-50"
|
||||
on:click={settingsViewModel.setName}
|
||||
toggle:disabled={settingsViewModel.cannotSetName}
|
||||
aria-label={translations.homePage.setNameButtonAudioLabel}
|
||||
aria-label={
|
||||
coreViewModel.translations.homePage
|
||||
.setNameButtonAudioLabel
|
||||
}
|
||||
>
|
||||
{translations.general.setButton}
|
||||
{coreViewModel.translations.general.setButton}
|
||||
<span class="icon">check</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -110,17 +125,17 @@ export function HomePage(
|
||||
|
||||
{HomePageButton(
|
||||
settingsViewModel.showSettingsModal,
|
||||
translations.homePage.settingsButton,
|
||||
coreViewModel.translations.homePage.settingsButton,
|
||||
"settings",
|
||||
)}
|
||||
{HomePageButton(
|
||||
fileTransferViewModel.showDirectionSelectionModal,
|
||||
translations.homePage.transferDataButton,
|
||||
coreViewModel.translations.homePage.transferDataButton,
|
||||
"sync_alt",
|
||||
)}
|
||||
{HomePageButton(
|
||||
storageViewModel.showStorageModal,
|
||||
translations.homePage.manageStorageButton,
|
||||
coreViewModel.translations.homePage.manageStorageButton,
|
||||
"hard_drive",
|
||||
)}
|
||||
|
||||
@@ -129,7 +144,7 @@ export function HomePage(
|
||||
|
||||
<div class="flex-row justify-end">
|
||||
<button class="ghost width-50" on:click={scrollToChat}>
|
||||
{translations.homePage.scrollToChatButton}
|
||||
{coreViewModel.translations.homePage.scrollToChatButton}
|
||||
<span class="icon">arrow_forward</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -139,18 +154,24 @@ export function HomePage(
|
||||
|
||||
const chatSection = (
|
||||
<div id="chat-section">
|
||||
<h2>{translations.homePage.chatsHeadline}</h2>
|
||||
<h2>{coreViewModel.translations.homePage.chatsHeadline}</h2>
|
||||
|
||||
<div class="flex-row width-input">
|
||||
<input
|
||||
placeholder={translations.homePage.addChatPlaceholder}
|
||||
aria-label={translations.homePage.addChatAudioLabel}
|
||||
placeholder={
|
||||
coreViewModel.translations.homePage.addChatPlaceholder
|
||||
}
|
||||
aria-label={
|
||||
coreViewModel.translations.homePage.addChatAudioLabel
|
||||
}
|
||||
bind:value={chatListViewModel.newChatPrimaryChannel}
|
||||
on:enter={chatListViewModel.createChat}
|
||||
></input>
|
||||
<button
|
||||
class="primary"
|
||||
aria-label={translations.homePage.addChatButton}
|
||||
aria-label={
|
||||
coreViewModel.translations.homePage.addChatButton
|
||||
}
|
||||
on:click={chatListViewModel.createChat}
|
||||
toggle:disabled={chatListViewModel.cannotCreateChat}
|
||||
>
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import * as React from "bloatless-react";
|
||||
import CoreViewModel from "../ViewModel/Global/coreViewModel";
|
||||
|
||||
import { translations } from "./translations";
|
||||
|
||||
export function MainPage() {
|
||||
export function MainPage(coreViewModel: CoreViewModel) {
|
||||
return (
|
||||
<article id="home-page">
|
||||
<header>
|
||||
<span>{translations.homePage.appName}</span>
|
||||
<span>{coreViewModel.translations.homePage.appName}</span>
|
||||
</header>
|
||||
<div></div>
|
||||
</article>
|
||||
|
||||
@@ -58,8 +58,6 @@ const englishTranslations = {
|
||||
yourNamePlaceholder: "Jane Doe",
|
||||
setNameButtonAudioLabel: "set name",
|
||||
|
||||
firstDayOfWeekLabel: "First day of week",
|
||||
|
||||
settingsButton: "Settings",
|
||||
manageStorageButton: "Manage storage",
|
||||
transferDataButton: "Data Transfer",
|
||||
@@ -84,6 +82,9 @@ const englishTranslations = {
|
||||
},
|
||||
|
||||
version: "Version",
|
||||
language: "Language",
|
||||
|
||||
firstDayOfWeekLabel: "First day of week",
|
||||
},
|
||||
|
||||
connectionModal: {
|
||||
@@ -291,7 +292,9 @@ const englishTranslations = {
|
||||
},
|
||||
};
|
||||
|
||||
const allTranslations: { [language: string]: typeof englishTranslations } = {
|
||||
export const allTranslations: {
|
||||
[language: string]: typeof englishTranslations;
|
||||
} = {
|
||||
en: englishTranslations,
|
||||
|
||||
de: {
|
||||
@@ -352,8 +355,6 @@ const allTranslations: { [language: string]: typeof englishTranslations } = {
|
||||
yourNamePlaceholder: "Max Mustermann",
|
||||
setNameButtonAudioLabel: "Name speichern",
|
||||
|
||||
firstDayOfWeekLabel: "Erster Wochentag",
|
||||
|
||||
settingsButton: "Einstellungen",
|
||||
manageStorageButton: "Daten verwalten",
|
||||
transferDataButton: "Datenübertragung",
|
||||
@@ -376,6 +377,9 @@ const allTranslations: { [language: string]: typeof englishTranslations } = {
|
||||
},
|
||||
|
||||
version: "Version",
|
||||
language: "Sprache",
|
||||
|
||||
firstDayOfWeekLabel: "Erster Wochentag",
|
||||
},
|
||||
|
||||
connectionModal: {
|
||||
@@ -615,8 +619,6 @@ const allTranslations: { [language: string]: typeof englishTranslations } = {
|
||||
yourNamePlaceholder: "Juan Pérez",
|
||||
setNameButtonAudioLabel: "establecer nombre",
|
||||
|
||||
firstDayOfWeekLabel: "Primer día de la semana",
|
||||
|
||||
settingsButton: "Ajustes",
|
||||
manageStorageButton: "Gestionar almacenamiento",
|
||||
transferDataButton: "Transferencia de datos",
|
||||
@@ -639,6 +641,9 @@ const allTranslations: { [language: string]: typeof englishTranslations } = {
|
||||
},
|
||||
|
||||
version: "Versión",
|
||||
language: "Idioma",
|
||||
|
||||
firstDayOfWeekLabel: "Primer día de la semana",
|
||||
},
|
||||
connectionModal: {
|
||||
connectionModalHeadline: "Gestionar Conexiones",
|
||||
@@ -823,5 +828,9 @@ const allTranslations: { [language: string]: typeof englishTranslations } = {
|
||||
},
|
||||
};
|
||||
|
||||
const language = navigator.language.substring(0, 2);
|
||||
export const translations = allTranslations[language] || allTranslations.en;
|
||||
export type Translations = typeof englishTranslations;
|
||||
export enum Languages {
|
||||
English = "en",
|
||||
German = "de",
|
||||
Spanish = "es",
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@ import ConnectionViewModel from "../Global/connectionViewModel";
|
||||
import NotificationViewModel from "../Global/notificationViewModel";
|
||||
|
||||
export default class ChatListViewModel {
|
||||
storageModel: StorageModel;
|
||||
chatListModel: ChatListModel;
|
||||
settingsViewModel: SettingsViewModel;
|
||||
notificationViewModel: NotificationViewModel;
|
||||
connectionViewModel: ConnectionViewModel;
|
||||
@@ -39,9 +37,10 @@ export default class ChatListViewModel {
|
||||
|
||||
// methods
|
||||
createChat = (): void => {
|
||||
const chatModel: ChatModel = this.chatListModel.createChat(
|
||||
this.newChatPrimaryChannel.value,
|
||||
);
|
||||
const chatModel: ChatModel =
|
||||
this.coreViewModel.chatListModel.createChat(
|
||||
this.newChatPrimaryChannel.value,
|
||||
);
|
||||
this.newChatPrimaryChannel.value = "";
|
||||
|
||||
const chatViewModel: ChatViewModel =
|
||||
@@ -55,14 +54,13 @@ export default class ChatListViewModel {
|
||||
};
|
||||
|
||||
untrackChat = (chatViewModel: ChatViewModel): void => {
|
||||
this.chatListModel.untrackChat(chatViewModel.chatModel);
|
||||
this.coreViewModel.chatListModel.untrackChat(chatViewModel.chatModel);
|
||||
this.chatViewModels.remove(chatViewModel);
|
||||
};
|
||||
|
||||
createChatViewModel = (chatModel: ChatModel): ChatViewModel => {
|
||||
return new ChatViewModel(
|
||||
this.coreViewModel,
|
||||
this.storageModel,
|
||||
chatModel,
|
||||
this.settingsViewModel,
|
||||
this.notificationViewModel,
|
||||
@@ -91,7 +89,7 @@ export default class ChatListViewModel {
|
||||
// load
|
||||
loadChats = (): void => {
|
||||
this.chatViewModels.clear();
|
||||
for (const chatModel of this.chatListModel.chatModels.values()) {
|
||||
for (const chatModel of this.coreViewModel.chatListModel.chatModels.values()) {
|
||||
const chatViewModel = this.createChatViewModel(chatModel);
|
||||
this.trackChat(chatViewModel);
|
||||
}
|
||||
@@ -101,13 +99,9 @@ export default class ChatListViewModel {
|
||||
// init
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
storageModel: StorageModel,
|
||||
chatListModel: ChatListModel,
|
||||
settingsViewModel: SettingsViewModel,
|
||||
connectionViewModel: ConnectionViewModel,
|
||||
) {
|
||||
this.storageModel = storageModel;
|
||||
this.chatListModel = chatListModel;
|
||||
this.settingsViewModel = settingsViewModel;
|
||||
this.notificationViewModel = new NotificationViewModel(this);
|
||||
this.connectionViewModel = connectionViewModel;
|
||||
|
||||
@@ -20,13 +20,12 @@ import MessagePageViewModel from "../Pages/messagePageViewModel";
|
||||
import SettingsPageViewModel from "../Pages/settingsPageViewModel";
|
||||
import SettingsViewModel from "../Global/settingsViewModel";
|
||||
import TaskPageViewModel from "../Pages/taskPageViewModel";
|
||||
import { translations } from "../../View/translations";
|
||||
import ConnectionViewModel from "../Global/connectionViewModel";
|
||||
import NotificationViewModel from "../Global/notificationViewModel";
|
||||
|
||||
export default class ChatViewModel {
|
||||
chatModel: ChatModel;
|
||||
storageModel: StorageModel;
|
||||
|
||||
settingsViewModel: SettingsViewModel;
|
||||
notificationViewModel: NotificationViewModel;
|
||||
connectionViewModel: ConnectionViewModel;
|
||||
@@ -84,13 +83,14 @@ export default class ChatViewModel {
|
||||
StorageModelSubPaths.Chat,
|
||||
filePaths.chat.lastUsedPage(this.chatModel.id),
|
||||
);
|
||||
const lastUsedPage: string | null = this.storageModel.read(path);
|
||||
const lastUsedPage: string | null =
|
||||
this.coreViewModel.storageModel.read(path);
|
||||
if (lastUsedPage != null) {
|
||||
this.selectedPage.value = lastUsedPage as any;
|
||||
}
|
||||
|
||||
this.selectedPage.subscribeSilent((newPage) => {
|
||||
this.storageModel.write(path, newPage);
|
||||
this.coreViewModel.storageModel.write(path, newPage);
|
||||
this.resetColor();
|
||||
});
|
||||
};
|
||||
@@ -99,7 +99,7 @@ export default class ChatViewModel {
|
||||
this.updateReadStatus();
|
||||
this.taskBoardSuggestions.set(CALENDAR_EVENT_BOARD_ID, [
|
||||
CALENDAR_EVENT_BOARD_ID,
|
||||
translations.chatPage.calendar.eventsBoard,
|
||||
this.coreViewModel.translations.chatPage.calendar.eventsBoard,
|
||||
]);
|
||||
};
|
||||
|
||||
@@ -132,7 +132,6 @@ export default class ChatViewModel {
|
||||
// init
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
storageModel: StorageModel,
|
||||
chatModel: ChatModel,
|
||||
settingsViewModel: SettingsViewModel,
|
||||
notificationViewModel: NotificationViewModel,
|
||||
@@ -140,7 +139,6 @@ export default class ChatViewModel {
|
||||
chatListViewModel: ChatListViewModel,
|
||||
) {
|
||||
// models
|
||||
this.storageModel = storageModel;
|
||||
this.chatModel = chatModel;
|
||||
this.settingsViewModel = settingsViewModel;
|
||||
this.connectionViewModel = connectionViewModel;
|
||||
@@ -151,14 +149,12 @@ export default class ChatViewModel {
|
||||
this.calendarViewModel = new CalendarPageViewModel(
|
||||
coreViewModel,
|
||||
this,
|
||||
this.storageModel,
|
||||
this.chatModel.fileModel.boardsAndTasksModel.calendarModel,
|
||||
this.chatModel.fileModel.boardsAndTasksModel,
|
||||
);
|
||||
this.taskPageViewModel = new TaskPageViewModel(
|
||||
this.coreViewModel,
|
||||
this,
|
||||
this.storageModel,
|
||||
this.chatModel.fileModel.boardsAndTasksModel,
|
||||
);
|
||||
this.messagePageViewModel = new MessagePageViewModel(
|
||||
|
||||
@@ -4,8 +4,6 @@ import ConnectionModel from "../../Model/Global/connectionModel";
|
||||
import CoreViewModel from "./coreViewModel";
|
||||
|
||||
export default class ConnectionViewModel {
|
||||
connectionModel: ConnectionModel;
|
||||
|
||||
// state
|
||||
serverAddressInput: React.State<string> = new React.State("");
|
||||
isConnected: React.State<boolean> = new React.State(false);
|
||||
@@ -20,7 +18,7 @@ export default class ConnectionViewModel {
|
||||
() =>
|
||||
(this.isConnected.value == true &&
|
||||
this.serverAddressInput.value ==
|
||||
this.connectionModel.address) ||
|
||||
this.coreViewModel.connectionModel.address) ||
|
||||
this.serverAddressInput.value == "",
|
||||
);
|
||||
cannotDisonnect: React.State<boolean> = React.createProxyState(
|
||||
@@ -34,15 +32,22 @@ export default class ConnectionViewModel {
|
||||
|
||||
// handlers
|
||||
connectionChangeHandler = (): void => {
|
||||
this.isConnected.value = this.connectionModel.isConnected;
|
||||
this.isConnected.value = this.coreViewModel.connectionModel.isConnected;
|
||||
|
||||
if (this.connectionModel.isConnected == false) return;
|
||||
if (this.connectionModel.address == undefined) return;
|
||||
if (this.coreViewModel.connectionModel.isConnected == false) return;
|
||||
if (this.coreViewModel.connectionModel.address == undefined) return;
|
||||
|
||||
this.serverAddressInput.value = this.connectionModel.address;
|
||||
this.serverAddressInput.value =
|
||||
this.coreViewModel.connectionModel.address;
|
||||
|
||||
if (!this.previousAddresses.value.has(this.connectionModel.address)) {
|
||||
this.previousAddresses.add(this.connectionModel.address);
|
||||
if (
|
||||
!this.previousAddresses.value.has(
|
||||
this.coreViewModel.connectionModel.address,
|
||||
)
|
||||
) {
|
||||
this.previousAddresses.add(
|
||||
this.coreViewModel.connectionModel.address,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -53,15 +58,15 @@ export default class ConnectionViewModel {
|
||||
|
||||
connectToAddress = (address: string): void => {
|
||||
console.log(address);
|
||||
this.connectionModel.connect(address);
|
||||
this.coreViewModel.connectionModel.connect(address);
|
||||
};
|
||||
|
||||
disconnect = (): void => {
|
||||
this.connectionModel.disconnect();
|
||||
this.coreViewModel.connectionModel.disconnect();
|
||||
};
|
||||
|
||||
removePreviousAddress = (address: string): void => {
|
||||
this.connectionModel.removeAddress(address);
|
||||
this.coreViewModel.connectionModel.removeAddress(address);
|
||||
this.updatePreviousAddresses();
|
||||
};
|
||||
|
||||
@@ -76,18 +81,16 @@ export default class ConnectionViewModel {
|
||||
|
||||
updatePreviousAddresses = (): void => {
|
||||
this.previousAddresses.clear();
|
||||
this.previousAddresses.add(...this.connectionModel.addresses);
|
||||
this.previousAddresses.add(
|
||||
...this.coreViewModel.connectionModel.addresses,
|
||||
);
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
connectionModel: ConnectionModel,
|
||||
) {
|
||||
this.connectionModel = connectionModel;
|
||||
constructor(public coreViewModel: CoreViewModel) {
|
||||
this.updatePreviousAddresses();
|
||||
|
||||
connectionModel.connectionChangeHandlerManager.addHandler(
|
||||
coreViewModel.connectionModel.connectionChangeHandlerManager.addHandler(
|
||||
this.connectionChangeHandler,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
import * as React from "bloatless-react";
|
||||
import SettingsModel from "../../Model/Global/settingsModel";
|
||||
import { allTranslations, Translations } from "../../View/translations";
|
||||
import StorageModel from "../../Model/Global/storageModel";
|
||||
import ConnectionModel from "../../Model/Global/connectionModel";
|
||||
import ChatListModel from "../../Model/Chat/chatListModel";
|
||||
import FileTransferModel from "../../Model/Global/fileTransferModel";
|
||||
|
||||
export default class CoreViewModel {
|
||||
readonly BUILD = "Build 26.04.08.C";
|
||||
readonly BUILD = "Build 26.04.09.A";
|
||||
|
||||
translations: Translations;
|
||||
|
||||
// DRAG & DROP
|
||||
draggedObject: React.State<any> = new React.State<any>(undefined);
|
||||
@@ -13,4 +21,16 @@ export default class CoreViewModel {
|
||||
|
||||
taskCategorySuggestions: React.ListState<string> = new React.ListState();
|
||||
taskStatusSuggestions: React.ListState<string> = new React.ListState();
|
||||
|
||||
// init
|
||||
constructor(
|
||||
public storageModel: StorageModel,
|
||||
public settingsModel: SettingsModel,
|
||||
public connectionModel: ConnectionModel,
|
||||
public chatListModel: ChatListModel,
|
||||
public fileTransferModel: FileTransferModel,
|
||||
) {
|
||||
this.translations =
|
||||
allTranslations[settingsModel.language] || allTranslations.en;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,12 +10,9 @@ import StorageModel, {
|
||||
|
||||
import ChatListModel from "../../Model/Chat/chatListModel";
|
||||
import ChatModel from "../../Model/Chat/chatModel";
|
||||
import { translations } from "../../View/translations";
|
||||
import CoreViewModel from "./coreViewModel";
|
||||
|
||||
export default class FileTransferViewModel {
|
||||
fileTransferModel: FileTransferModel;
|
||||
chatListModel: ChatListModel;
|
||||
|
||||
// state
|
||||
presentedModal: React.State<FileTransferModals | undefined> =
|
||||
new React.State<any>(undefined);
|
||||
@@ -40,7 +37,7 @@ export default class FileTransferViewModel {
|
||||
filesSentText: React.State<string> = React.createProxyState(
|
||||
[this.filesSentCount],
|
||||
() =>
|
||||
translations.dataTransferModal.filesSentCount(
|
||||
this.coreViewModel.translations.dataTransferModal.filesSentCount(
|
||||
this.filesSentCount.value,
|
||||
),
|
||||
);
|
||||
@@ -53,7 +50,7 @@ export default class FileTransferViewModel {
|
||||
filesReceivedText: React.State<string> = React.createProxyState(
|
||||
[this.filesReceivedCount],
|
||||
() =>
|
||||
translations.dataTransferModal.filesReceivedCount(
|
||||
this.coreViewModel.translations.dataTransferModal.filesReceivedCount(
|
||||
this.filesReceivedCount.value,
|
||||
),
|
||||
);
|
||||
@@ -84,14 +81,16 @@ export default class FileTransferViewModel {
|
||||
|
||||
this.generalFileOptions.add(
|
||||
{
|
||||
label: translations.dataTransferModal.connectionData,
|
||||
label: this.coreViewModel.translations.dataTransferModal
|
||||
.connectionData,
|
||||
path: StorageModel.getPath(
|
||||
StorageModelSubPaths.ConnectionModel,
|
||||
filePaths.connectionModel.previousAddresses,
|
||||
),
|
||||
},
|
||||
{
|
||||
label: translations.dataTransferModal.settingsData,
|
||||
label: this.coreViewModel.translations.dataTransferModal
|
||||
.settingsData,
|
||||
path: StorageModel.getPath(
|
||||
StorageModelSubPaths.SettingsModel,
|
||||
[],
|
||||
@@ -99,7 +98,8 @@ export default class FileTransferViewModel {
|
||||
},
|
||||
);
|
||||
|
||||
const chatModels: Set<ChatModel> = this.chatListModel.chatModels;
|
||||
const chatModels: Set<ChatModel> =
|
||||
this.coreViewModel.chatListModel.chatModels;
|
||||
for (const chatModel of chatModels) {
|
||||
this.chatFileOptions.add({
|
||||
label: chatModel.info.primaryChannel,
|
||||
@@ -110,7 +110,7 @@ export default class FileTransferViewModel {
|
||||
|
||||
getTransferData = (): void => {
|
||||
const transferData: TransferData =
|
||||
this.fileTransferModel.generateTransferData();
|
||||
this.coreViewModel.fileTransferModel.generateTransferData();
|
||||
this.transferChannel.value = transferData.channel;
|
||||
this.transferKey.value = transferData.key;
|
||||
};
|
||||
@@ -128,7 +128,7 @@ export default class FileTransferViewModel {
|
||||
showTransferDataModal = (): void => {
|
||||
this.presentedModal.value = FileTransferModals.TransferDataDisplay;
|
||||
this.getTransferData();
|
||||
this.fileTransferModel.prepareToSend();
|
||||
this.coreViewModel.fileTransferModel.prepareToSend();
|
||||
};
|
||||
|
||||
initiateTransfer = (): void => {
|
||||
@@ -136,7 +136,7 @@ export default class FileTransferViewModel {
|
||||
this.didNotFinishSending.value = true;
|
||||
this.filePathsSent.clear();
|
||||
|
||||
this.fileTransferModel.sendFiles(
|
||||
this.coreViewModel.fileTransferModel.sendFiles(
|
||||
this.selectedPaths.value.values(),
|
||||
(path: string) => {
|
||||
console.log(path);
|
||||
@@ -159,7 +159,7 @@ export default class FileTransferViewModel {
|
||||
channel: this.receivingTransferChannel.value,
|
||||
key: this.receivingTransferKey.value,
|
||||
};
|
||||
this.fileTransferModel.prepareToReceive(transferData);
|
||||
this.coreViewModel.fileTransferModel.prepareToReceive(transferData);
|
||||
};
|
||||
|
||||
hideModal = (): void => {
|
||||
@@ -167,19 +167,13 @@ export default class FileTransferViewModel {
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(
|
||||
fileTransferModel: FileTransferModel,
|
||||
chatListModel: ChatListModel,
|
||||
) {
|
||||
this.fileTransferModel = fileTransferModel;
|
||||
this.chatListModel = chatListModel;
|
||||
|
||||
this.fileTransferModel.fileHandlerManager.addHandler(
|
||||
constructor(public coreViewModel: CoreViewModel) {
|
||||
this.coreViewModel.fileTransferModel.fileHandlerManager.addHandler(
|
||||
this.handleReceivedFile,
|
||||
);
|
||||
|
||||
this.fileTransferModel.readyToSendHandlerManager.addHandler(() =>
|
||||
this.initiateTransfer(),
|
||||
this.coreViewModel.fileTransferModel.readyToSendHandlerManager.addHandler(
|
||||
() => this.initiateTransfer(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,36 +2,40 @@ import * as React from "bloatless-react";
|
||||
|
||||
import CoreViewModel from "./coreViewModel";
|
||||
import SettingsModel from "../../Model/Global/settingsModel";
|
||||
import { Languages } from "../../View/translations";
|
||||
|
||||
export default class SettingsViewModel {
|
||||
settingsModel: SettingsModel;
|
||||
|
||||
// state
|
||||
username: React.State<string> = new React.State("");
|
||||
usernameInput: React.State<string> = new React.State("");
|
||||
firstDayOfWeekInput: React.State<string> = new React.State("0");
|
||||
isShowingSettingsModal: React.State<boolean> = new React.State(false);
|
||||
selectedModalPage: React.State<SettingsModalPages> = new React.State(
|
||||
SettingsModalPages.Appearance,
|
||||
);
|
||||
|
||||
firstDayOfWeek: React.State<string> = new React.State("0");
|
||||
language: React.State<Languages> = new React.State(Languages.English);
|
||||
|
||||
// guards
|
||||
cannotSetName: React.State<boolean> = React.createProxyState(
|
||||
[this.usernameInput],
|
||||
() =>
|
||||
this.usernameInput.value == "" ||
|
||||
this.usernameInput.value == this.settingsModel.username,
|
||||
this.usernameInput.value ==
|
||||
this.coreViewModel.settingsModel.username,
|
||||
);
|
||||
|
||||
// methods
|
||||
setName = (): void => {
|
||||
this.settingsModel.setName(this.usernameInput.value);
|
||||
this.username.value = this.settingsModel.username;
|
||||
this.coreViewModel.settingsModel.setName(this.usernameInput.value);
|
||||
this.username.value = this.coreViewModel.settingsModel.username;
|
||||
this.usernameInput.callSubscriptions();
|
||||
};
|
||||
|
||||
setFirstDayofWeek = (): void => {
|
||||
this.settingsModel.setFirstDayOfWeek(this.firstDayOfWeekInput.value);
|
||||
this.coreViewModel.settingsModel.setFirstDayOfWeek(
|
||||
this.firstDayOfWeek.value,
|
||||
);
|
||||
};
|
||||
|
||||
showSettingsModal = (): void => {
|
||||
@@ -47,18 +51,13 @@ export default class SettingsViewModel {
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
settingsModel: SettingsModel,
|
||||
) {
|
||||
this.settingsModel = settingsModel;
|
||||
|
||||
this.username.value = settingsModel.username;
|
||||
this.usernameInput.value = settingsModel.username;
|
||||
this.firstDayOfWeekInput.value = settingsModel.firstDayOfWeek;
|
||||
constructor(public coreViewModel: CoreViewModel) {
|
||||
this.username.value = coreViewModel.settingsModel.username;
|
||||
this.usernameInput.value = coreViewModel.settingsModel.username;
|
||||
this.firstDayOfWeek.value = coreViewModel.settingsModel.firstDayOfWeek;
|
||||
|
||||
// subscriptions
|
||||
this.firstDayOfWeekInput.subscribe(this.setFirstDayofWeek);
|
||||
this.firstDayOfWeek.subscribe(this.setFirstDayofWeek);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,8 @@ import StorageModel, {
|
||||
} from "../../Model/Global/storageModel";
|
||||
|
||||
import CoreViewModel from "./coreViewModel";
|
||||
import { translations } from "../../View/translations";
|
||||
|
||||
export default class StorageViewModel {
|
||||
storageModel: StorageModel;
|
||||
|
||||
// state
|
||||
isShowingStorageModal: React.State<boolean> = new React.State(false);
|
||||
selectedPath: React.State<string> = new React.State(
|
||||
@@ -27,10 +24,10 @@ export default class StorageViewModel {
|
||||
const path = StorageModel.stringToPathComponents(
|
||||
this.selectedPath.value,
|
||||
);
|
||||
const content = this.storageModel.read(path);
|
||||
const content = this.coreViewModel.storageModel.read(path);
|
||||
return (
|
||||
(content ?? translations.storage.notAFile) ||
|
||||
translations.storage.contentEmpty
|
||||
(content ?? this.coreViewModel.translations.storage.notAFile) ||
|
||||
this.coreViewModel.translations.storage.contentEmpty
|
||||
);
|
||||
};
|
||||
|
||||
@@ -40,12 +37,12 @@ export default class StorageViewModel {
|
||||
);
|
||||
this.lastDeletedItemPath.value = this.selectedPath.value;
|
||||
|
||||
this.storageModel.removeRecursively(path);
|
||||
this.coreViewModel.storageModel.removeRecursively(path);
|
||||
this.didMakeChanges.value = true;
|
||||
};
|
||||
|
||||
removeJunk = (): void => {
|
||||
this.storageModel.removeJunk();
|
||||
this.coreViewModel.storageModel.removeJunk();
|
||||
this.selectedPath.value = PATH_COMPONENT_SEPARATOR;
|
||||
};
|
||||
|
||||
@@ -63,12 +60,7 @@ export default class StorageViewModel {
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
storageModel: StorageModel,
|
||||
) {
|
||||
this.storageModel = storageModel;
|
||||
|
||||
constructor(public coreViewModel: CoreViewModel) {
|
||||
this.selectedFileName = React.createProxyState(
|
||||
[this.selectedPath],
|
||||
() => StorageModel.getFileNameFromString(this.selectedPath.value),
|
||||
|
||||
@@ -15,7 +15,6 @@ import TaskPageViewModel from "./taskPageViewModel";
|
||||
import TaskViewModel from "./taskViewModel";
|
||||
|
||||
export default class BoardViewModel extends TaskContainingPageViewModel {
|
||||
storageModel: StorageModel;
|
||||
boardsAndTasksModel: BoardsAndTasksModel;
|
||||
|
||||
taskPageViewModel: TaskPageViewModel;
|
||||
@@ -104,12 +103,13 @@ export default class BoardViewModel extends TaskContainingPageViewModel {
|
||||
storeLastUsedView = (): void => {
|
||||
const path: string[] = this.getLastUsedBoardPath();
|
||||
const lastUsedView: string = this.selectedPage.value;
|
||||
this.storageModel.write(path, lastUsedView);
|
||||
this.coreViewModel.storageModel.write(path, lastUsedView);
|
||||
};
|
||||
|
||||
restoreLastUsedView = (): void => {
|
||||
const path: string[] = this.getLastUsedBoardPath();
|
||||
const lastUsedView: string | null = this.storageModel.read(path);
|
||||
const lastUsedView: string | null =
|
||||
this.coreViewModel.storageModel.read(path);
|
||||
if (lastUsedView == null) return;
|
||||
|
||||
this.selectedPage.value = lastUsedView as BoardPageTypes;
|
||||
@@ -120,7 +120,7 @@ export default class BoardViewModel extends TaskContainingPageViewModel {
|
||||
...this.getPreviousSearchesPath(),
|
||||
searchTerm,
|
||||
];
|
||||
this.storageModel.write(suggestionPath, "");
|
||||
this.coreViewModel.storageModel.write(suggestionPath, "");
|
||||
if (
|
||||
!this.coreViewModel.boardFilterStringSuggestions.value.has(
|
||||
searchTerm,
|
||||
@@ -130,7 +130,7 @@ export default class BoardViewModel extends TaskContainingPageViewModel {
|
||||
}
|
||||
|
||||
const lastSearchPath: string[] = this.getLastSearchPath();
|
||||
this.storageModel.write(lastSearchPath, searchTerm);
|
||||
this.coreViewModel.storageModel.write(lastSearchPath, searchTerm);
|
||||
};
|
||||
|
||||
// view
|
||||
@@ -224,14 +224,15 @@ export default class BoardViewModel extends TaskContainingPageViewModel {
|
||||
|
||||
loadSearchSuggestions = (): void => {
|
||||
const dirPath: string[] = this.getPreviousSearchesPath();
|
||||
const searches: string[] = this.storageModel.list(dirPath);
|
||||
const searches: string[] =
|
||||
this.coreViewModel.storageModel.list(dirPath);
|
||||
this.coreViewModel.boardFilterStringSuggestions.add(...searches);
|
||||
};
|
||||
|
||||
restoreSearch = (): void => {
|
||||
const lastSearchPath: string[] = this.getLastSearchPath();
|
||||
const lastSearch: string | null =
|
||||
this.storageModel.read(lastSearchPath);
|
||||
this.coreViewModel.storageModel.read(lastSearchPath);
|
||||
if (lastSearch != null) {
|
||||
this.searchViewModel.search(lastSearch);
|
||||
}
|
||||
@@ -247,7 +248,6 @@ export default class BoardViewModel extends TaskContainingPageViewModel {
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
public chatViewModel: ChatViewModel,
|
||||
storageModel: StorageModel,
|
||||
boardsAndTasksModel: BoardsAndTasksModel,
|
||||
taskPageViewModel: TaskPageViewModel,
|
||||
boardInfo: BoardInfoFileContent,
|
||||
@@ -255,7 +255,6 @@ export default class BoardViewModel extends TaskContainingPageViewModel {
|
||||
super(coreViewModel, chatViewModel, boardsAndTasksModel);
|
||||
|
||||
// set
|
||||
this.storageModel = storageModel;
|
||||
this.boardsAndTasksModel = boardsAndTasksModel;
|
||||
this.taskPageViewModel = taskPageViewModel;
|
||||
this.boardInfo = boardInfo;
|
||||
|
||||
@@ -14,7 +14,6 @@ import TaskViewModel from "./taskViewModel";
|
||||
export const CALENDAR_EVENT_BOARD_ID = "events";
|
||||
|
||||
export default class CalendarPageViewModel extends TaskContainingPageViewModel {
|
||||
storageModel: StorageModel;
|
||||
calendarModel: CalendarModel;
|
||||
boardsAndTasksModel: BoardsAndTasksModel;
|
||||
|
||||
@@ -189,13 +188,11 @@ export default class CalendarPageViewModel extends TaskContainingPageViewModel {
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
public chatViewModel: ChatViewModel,
|
||||
storageModel: StorageModel,
|
||||
calendarModel: CalendarModel,
|
||||
boardsAndTasksModel: BoardsAndTasksModel,
|
||||
) {
|
||||
super(coreViewModel, chatViewModel, boardsAndTasksModel);
|
||||
|
||||
this.storageModel = storageModel;
|
||||
this.calendarModel = calendarModel;
|
||||
this.boardsAndTasksModel = boardsAndTasksModel;
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import { IndexManager } from "../../Model/Utility/utility";
|
||||
import StorageModel from "../../Model/Global/storageModel";
|
||||
|
||||
export default class TaskPageViewModel {
|
||||
storageModel: StorageModel;
|
||||
boardsAndTasksModel: BoardsAndTasksModel;
|
||||
|
||||
// data
|
||||
@@ -82,7 +81,6 @@ export default class TaskPageViewModel {
|
||||
const boardViewModel: BoardViewModel = new BoardViewModel(
|
||||
this.coreViewModel,
|
||||
this.chatViewModel,
|
||||
this.storageModel,
|
||||
this.boardsAndTasksModel,
|
||||
this,
|
||||
boardInfo,
|
||||
@@ -120,12 +118,13 @@ export default class TaskPageViewModel {
|
||||
storeLastUsedBoard = (): void => {
|
||||
const path: string[] = this.getLastUsedBoardPath();
|
||||
const lastUsedBoardId: string = this.selectedBoardId.value ?? "";
|
||||
this.storageModel.write(path, lastUsedBoardId);
|
||||
this.coreViewModel.storageModel.write(path, lastUsedBoardId);
|
||||
};
|
||||
|
||||
openLastUsedBoard = (): void => {
|
||||
const path: string[] = this.getLastUsedBoardPath();
|
||||
const lastUsedBoardId: string | null = this.storageModel.read(path);
|
||||
const lastUsedBoardId: string | null =
|
||||
this.coreViewModel.storageModel.read(path);
|
||||
if (lastUsedBoardId == null) return;
|
||||
|
||||
const boardViewModel: BoardViewModel | undefined =
|
||||
@@ -156,10 +155,8 @@ export default class TaskPageViewModel {
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
public chatViewModel: ChatViewModel,
|
||||
storageModel: StorageModel,
|
||||
boardModel: BoardsAndTasksModel,
|
||||
) {
|
||||
this.storageModel = storageModel;
|
||||
this.boardsAndTasksModel = boardModel;
|
||||
|
||||
this.chatViewModel = chatViewModel;
|
||||
|
||||
+25
-22
@@ -33,29 +33,28 @@ const chatListModel = new ChatListModel(
|
||||
connectionModel,
|
||||
);
|
||||
const fileTransferModel = new FileTransferModel(storageModel, connectionModel);
|
||||
// upgrade
|
||||
new v1Upgrader(settingsModel, connectionModel, chatListModel);
|
||||
|
||||
// viewModels
|
||||
const coreVieWModel = new CoreViewModel();
|
||||
|
||||
const storageViewModel = new StorageViewModel(coreVieWModel, storageModel);
|
||||
const settingsViewModel = new SettingsViewModel(coreVieWModel, settingsModel);
|
||||
const connectionViewModel = new ConnectionViewModel(
|
||||
coreVieWModel,
|
||||
connectionModel,
|
||||
);
|
||||
const chatListViewModel = new ChatListViewModel(
|
||||
coreVieWModel,
|
||||
const coreViewModel = new CoreViewModel(
|
||||
storageModel,
|
||||
settingsModel,
|
||||
connectionModel,
|
||||
chatListModel,
|
||||
fileTransferModel,
|
||||
);
|
||||
|
||||
// upgrade
|
||||
new v1Upgrader(coreViewModel);
|
||||
|
||||
const storageViewModel = new StorageViewModel(coreViewModel);
|
||||
const settingsViewModel = new SettingsViewModel(coreViewModel);
|
||||
const connectionViewModel = new ConnectionViewModel(coreViewModel);
|
||||
const chatListViewModel = new ChatListViewModel(
|
||||
coreViewModel,
|
||||
settingsViewModel,
|
||||
connectionViewModel,
|
||||
);
|
||||
const fileTransferViewModel = new FileTransferViewModel(
|
||||
fileTransferModel,
|
||||
chatListModel,
|
||||
);
|
||||
const fileTransferViewModel = new FileTransferViewModel(coreViewModel);
|
||||
|
||||
// view
|
||||
chatListViewModel.selectedChat.subscribe(() => {
|
||||
@@ -76,16 +75,20 @@ document
|
||||
.querySelector("main")!
|
||||
.append(
|
||||
HomePage(
|
||||
coreVieWModel,
|
||||
coreViewModel,
|
||||
storageViewModel,
|
||||
settingsViewModel,
|
||||
connectionViewModel,
|
||||
fileTransferViewModel,
|
||||
chatListViewModel,
|
||||
),
|
||||
ChatPageWrapper(chatListViewModel),
|
||||
ConnectionModal(connectionViewModel),
|
||||
DataTransferModalWrapper(connectionViewModel, fileTransferViewModel),
|
||||
StorageModal(storageViewModel),
|
||||
SettingsModal(settingsViewModel),
|
||||
ChatPageWrapper(coreViewModel, chatListViewModel),
|
||||
ConnectionModal(coreViewModel, connectionViewModel),
|
||||
DataTransferModalWrapper(
|
||||
coreViewModel,
|
||||
connectionViewModel,
|
||||
fileTransferViewModel,
|
||||
),
|
||||
StorageModal(coreViewModel, storageViewModel),
|
||||
SettingsModal(coreViewModel, settingsViewModel),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user