move translations to CoreVM, move models to CoreVM for sentralization

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