clean model (A)

This commit is contained in:
marlon-erler
2026-04-18 11:55:01 +00:00
parent cae717066a
commit 2ae00924c8
75 changed files with 5139 additions and 5147 deletions
+9
View File
@@ -0,0 +1,9 @@
trailingComma: "all"
tabWidth: 4
semi: true
singleQuote: false
plugins:
- "prettier-plugin-sort-imports"
sortingMethod: "alphabetical"
sortingOrder: "ascending"
stripNewlines: true
BIN
View File
Binary file not shown.
+304 -304
View File
@@ -1,78 +1,3 @@
/* src/base.css */
#home-page,
#home-page #chat-section,
#chat-page,
#chat-page #main > div {
animation: slide-up var(--animation-duration) ease;
}
#background-wrapper {
position: fixed;
top: 0px;
left: var(--safe-area-left);
right: var(--safe-area-right);
bottom: 0px;
z-index: 1;
pointer-events: none;
overflow: hidden;
opacity: 0.4;
}
main {
z-index: 2;
}
#background-wrapper div {
content: "";
position: absolute;
top: -80px;
left: -80px;
right: -80px;
bottom: -80px;
z-index: -1;
pointer-events: none;
filter: blur(40px);
}
#background-wrapper #sky {
left: -100%;
bottom: -50%;
--color-1: hsl(188, 100%, 83%);
--color-2: hsl(194, 72%, 56%);
background-image: radial-gradient(var(--color-1), var(--color-2));
}
#background-wrapper #grass-1 {
--color-1: hsl(150, 100%, 30%);
--color-2: hsl(150, 100%, 25%);
background-image:
linear-gradient(
350deg,
var(--color-1),
var(--color-2) 30%,
transparent 40%);
}
#background-wrapper #grass-2 {
--color-1: hsl(110, 100%, 40%);
--color-2: hsl(110, 100%, 35%);
background-image:
linear-gradient(
9deg,
var(--color-1),
var(--color-2) 30%,
transparent 35%);
}
body[theme=dark] #background-wrapper {
opacity: 0.5;
}
body[theme=dark] #background-wrapper #sky {
--color-1: hsl(188, 100%, 30%);
--color-2: hsl(194, 72%, 24%);
}
body[theme=dark] #background-wrapper #grass-1 {
--color-1: hsl(120, 30%, 30%);
--color-2: hsl(120, 30%, 24%);
}
body[theme=dark] #background-wrapper #grass-2 {
--color-1: hsl(110, 60%, 30%);
--color-2: hsl(110, 50%, 24%);
}
/* src/colors.css */
[color]:not([color=standard]) {
--primary: hsl(var(--hue), 100%, var(--accent-luma));
@@ -238,6 +163,143 @@ body[theme=dark] [color]:not([color=standard]).subtle-background {
white-space: nowrap;
}
/* src/base.css */
#home-page,
#home-page #chat-section,
#chat-page,
#chat-page #main > div {
animation: slide-up var(--animation-duration) ease;
}
#background-wrapper {
position: fixed;
top: 0px;
left: var(--safe-area-left);
right: var(--safe-area-right);
bottom: 0px;
z-index: 1;
pointer-events: none;
overflow: hidden;
opacity: 0.4;
}
main {
z-index: 2;
}
#background-wrapper div {
content: "";
position: absolute;
top: -80px;
left: -80px;
right: -80px;
bottom: -80px;
z-index: -1;
pointer-events: none;
filter: blur(40px);
}
#background-wrapper #sky {
left: -100%;
bottom: -50%;
--color-1: hsl(188, 100%, 83%);
--color-2: hsl(194, 72%, 56%);
background-image: radial-gradient(var(--color-1), var(--color-2));
}
#background-wrapper #grass-1 {
--color-1: hsl(150, 100%, 30%);
--color-2: hsl(150, 100%, 25%);
background-image:
linear-gradient(
350deg,
var(--color-1),
var(--color-2) 30%,
transparent 40%);
}
#background-wrapper #grass-2 {
--color-1: hsl(110, 100%, 40%);
--color-2: hsl(110, 100%, 35%);
background-image:
linear-gradient(
9deg,
var(--color-1),
var(--color-2) 30%,
transparent 35%);
}
body[theme=dark] #background-wrapper {
opacity: 0.5;
}
body[theme=dark] #background-wrapper #sky {
--color-1: hsl(188, 100%, 30%);
--color-2: hsl(194, 72%, 24%);
}
body[theme=dark] #background-wrapper #grass-1 {
--color-1: hsl(120, 30%, 30%);
--color-2: hsl(120, 30%, 24%);
}
body[theme=dark] #background-wrapper #grass-2 {
--color-1: hsl(110, 60%, 30%);
--color-2: hsl(110, 50%, 24%);
}
/* src/View/homePage.css */
#home-page > div {
display: flex;
flex-direction: row;
gap: var(--large-gap);
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
overflow: hidden;
overflow-x: scroll;
padding: 0px;
}
#home-page > div > div {
display: flex;
flex-direction: column;
justify-content: start;
gap: var(--gap-between-tiles);
padding: var(--content-padding);
padding-top: calc(var(--header-height) + var(--content-margin));
width: 100%;
min-width: 100%;
height: 100%;
overflow-y: auto;
scroll-snap-align: center;
}
#home-page #overview-section,
#home-page #chat-section {
padding-bottom: calc(var(--content-padding) + var(--header-height) + var(--safe-area-bottom));
}
#home-page #chat-grid {
margin-top: var(--content-padding);
display: grid;
gap: var(--gap-between-tiles);
grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
}
@media (min-width: 640px) {
#home-page > div {
overflow-x: hidden;
}
#home-page #overview-section {
width: 20rem;
min-width: 20rem;
}
#home-page #chat-section {
flex: 1;
min-width: unset;
}
}
@media (min-width: 1200px) {
#home-page #overview-section,
#home-page #chat-section {
padding-left: 3rem;
padding-right: 3rem;
}
#home-page #chat-grid {
margin-top: 3rem;
}
#home-page #overview-section {
width: var(--max-input-width);
min-width: var(--max-input-width);
}
}
/* src/View/chatPage.css */
#chat-page-wrapper {
display: none;
@@ -408,179 +470,95 @@ body[showing-chat] #chat-page-wrapper {
flex: 1;
}
/* src/View/homePage.css */
#home-page > div {
display: flex;
flex-direction: row;
gap: var(--large-gap);
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
overflow: hidden;
overflow-x: scroll;
/* src/View/ChatPages/taskPage.css */
#chat-page > div > #main > #task-page > .pane-wrapper > .pane > .main-content {
width: 100%;
max-width: 100%;
padding: 0px;
}
#home-page > div > div {
#chat-page > div > #main > #task-page > .pane-wrapper > .pane > .main-content > div {
animation: slide-up var(--animation-duration);
}
#chat-page > div > #main > #task-page .task-grid {
display: flex;
flex-direction: column;
justify-content: start;
gap: var(--gap-between-tiles);
padding: var(--content-padding);
padding-top: calc(var(--header-height) + var(--content-margin));
}
#chat-page > div > #main > #task-page .kanban-board-wrapper,
#chat-page > div > #main > #task-page .status-page-content {
display: flex;
align-items: start;
gap: var(--large-gap);
width: 100%;
min-width: 100%;
height: 100%;
overflow-y: auto;
scroll-snap-align: center;
}
#home-page #overview-section,
#home-page #chat-section {
padding-bottom: calc(var(--content-padding) + var(--header-height) + var(--safe-area-bottom));
}
#home-page #chat-grid {
margin-top: var(--content-padding);
display: grid;
gap: var(--gap-between-tiles);
grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
}
@media (min-width: 640px) {
#home-page > div {
overflow-x: hidden;
}
#home-page #overview-section {
width: 20rem;
min-width: 20rem;
}
#home-page #chat-section {
flex: 1;
min-width: unset;
}
}
@media (min-width: 1200px) {
#home-page #overview-section,
#home-page #chat-section {
padding-left: 3rem;
padding-right: 3rem;
}
#home-page #chat-grid {
margin-top: 3rem;
}
#home-page #overview-section {
width: var(--max-input-width);
min-width: var(--max-input-width);
}
}
/* src/View/ChatPages/calendarPage.css */
#chat-page > div > #main > #calendar-page > .pane-wrapper > .pane > .toolbar .input-wrapper {
display: flex;
padding: var(--gap-between-tiles);
gap: var(--gap-between-tiles);
}
#chat-page > div > #main > #calendar-page > .pane-wrapper > .pane > .toolbar .input-wrapper > input {
min-height: unset;
height: calc(var(--control-height) - 2 * var(--gap-between-tiles));
appearance: textfield;
-moz-appearance: textfield;
padding-right: 0px;
}
#calendar-page .input-wrapper > input::-webkit-outer-spin-button,
#calendar-page .input-wrapper > input::-webkit-innner-spin-button {
appearance: none;
-webkit-appearance: none;
margin: 0px;
}
#chat-page > div > #main > #calendar-page > .pane-wrapper > .pane > .toolbar .input-wrapper > .year-input {
width: 4.4rem;
}
#chat-page > div > #main > #calendar-page > .pane-wrapper > .pane > .toolbar .input-wrapper > .month-input {
width: 3.1rem;
}
@media (max-width: 1024px) {
#chat-page > div > #main > #calendar-page {
flex-direction: column;
}
#chat-page > div > #main > #calendar-page .grid-pane-wrapper {
border-bottom: 1px solid var(--border);
}
}
/* src/View/Components/monthGrid.css */
.month-grid-wrapper {
display: flex;
flex-direction: column;
gap: var(--gap-between-tiles);
height: 100%;
overflow: auto;
}
.month-grid-wrapper .day-labels {
flex: 0;
padding: var(--content-padding);
padding-bottom: 0px;
}
.month-grid-wrapper > div {
display: grid;
gap: var(--gap-between-tiles);
grid-template-columns: repeat(7, minmax(0px, 1fr));
animation: slide-up var(--animation-duration);
}
.month-grid {
overflow: visible;
padding: var(--content-padding);
padding-top: 0px;
flex: 1;
grid-auto-rows: 1fr;
}
.month-grid .tile {
animation: slide-up var(--animation-duration);
overflow: hidden;
align-items: start;
}
.month-grid .tile[today] b {
color: var(--primary);
}
.month-grid .tile > div {
width: 100%;
height: 100%;
}
.month-grid .tile .event-count {
display: none;
background-color: var(--text-normal);
color: var(--background);
opacity: 0.6;
border-radius: 100%;
width: 1rem;
height: 1rem;
font-size: 0.6rem;
font-weight: bold;
align-items: center;
justify-content: center;
}
.month-grid .tile .event-count[has-events] {
background-color: var(--primary);
opacity: 1;
}
.month-grid .tile .event-list {
#chat-page > div > #main > #task-page .kanban-board-wrapper .kanban-column,
#chat-page > div > #main > #task-page .status-grid-wrapper .status-column {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
gap: var(--gap-between-tiles);
}
.month-grid .tile .event-list span {
animation: slide-up var(--animation-duration);
#chat-page > div > #main > #task-page .property-input-wrapper {
display: flex;
flex-direction: row;
}
@media (max-width: 640px) and (max-height: 1200px) {
.month-grid .tile {
padding: 0px;
#chat-page > div > #main > #task-page .kanban-board-wrapper .kanban-column,
#chat-page > div > #main > #task-page .property-input-wrapper,
#chat-page > div > #main > #task-page .status-grid-wrapper .status-column,
#chat-page > div > #main > #task-page .status-name-row > *,
#chat-page > div > #main > #task-page .status-name-row::before {
width: 18rem;
min-width: 18rem;
max-width: 18rem;
}
#chat-page > div > #main > #task-page .status-name-row,
#chat-page > div > #main > #task-page .status-grid-wrapper {
display: flex;
gap: var(--large-gap);
}
#chat-page > div > #main > #task-page .status-page-content,
#chat-page > div > #main > #task-page .status-grid-wrapper {
flex-direction: column;
}
#chat-page > div > #main > #task-page .status-name-row::before {
content: "";
display: flex;
}
#chat-page > div > #main > #task-page .board-close-button {
display: none;
}
#chat-page > div > #main > #task-page .board-toggle-button {
display: flex;
}
#chat-page > div > #main > #task-page[isshowingboard][showingboardlist=false] #board-list {
display: none;
}
@media (min-width: 640px) {
#chat-page > div > #main > #task-page .task-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
}
.month-grid .tile > div {
align-items: center;
justify-content: center;
}
@media (max-width: 1024px) {
#chat-page > div > #main > #task-page #board-list {
display: false;
}
.month-grid .tile .event-count {
#chat-page > div > #main > #task-page #board-content {
display: none;
}
#chat-page > div > #main > #task-page[isshowingboard] #board-list {
display: none;
}
#chat-page > div > #main > #task-page[isshowingboard] #board-content {
display: flex;
}
.month-grid .tile .event-list {
#chat-page > div > #main > #task-page .board-close-button {
display: flex;
}
#chat-page > div > #main > #task-page .board-toggle-button {
display: none;
}
}
@@ -810,95 +788,117 @@ body[showing-chat] #chat-page-wrapper {
grid-template-columns: repeat(3, 1fr);
}
/* src/View/ChatPages/taskPage.css */
#chat-page > div > #main > #task-page > .pane-wrapper > .pane > .main-content {
width: 100%;
max-width: 100%;
padding: 0px;
}
#chat-page > div > #main > #task-page > .pane-wrapper > .pane > .main-content > div {
animation: slide-up var(--animation-duration);
}
#chat-page > div > #main > #task-page .task-grid {
/* src/View/ChatPages/calendarPage.css */
#chat-page > div > #main > #calendar-page > .pane-wrapper > .pane > .toolbar .input-wrapper {
display: flex;
flex-direction: column;
gap: var(--gap-between-tiles);
padding: var(--content-padding);
}
#chat-page > div > #main > #task-page .kanban-board-wrapper,
#chat-page > div > #main > #task-page .status-page-content {
display: flex;
align-items: start;
gap: var(--large-gap);
width: 100%;
height: 100%;
overflow: auto;
padding: var(--content-padding);
}
#chat-page > div > #main > #task-page .kanban-board-wrapper .kanban-column,
#chat-page > div > #main > #task-page .status-grid-wrapper .status-column {
display: flex;
flex-direction: column;
padding: var(--gap-between-tiles);
gap: var(--gap-between-tiles);
}
#chat-page > div > #main > #task-page .property-input-wrapper {
display: flex;
flex-direction: row;
#chat-page > div > #main > #calendar-page > .pane-wrapper > .pane > .toolbar .input-wrapper > input {
min-height: unset;
height: calc(var(--control-height) - 2 * var(--gap-between-tiles));
appearance: textfield;
-moz-appearance: textfield;
padding-right: 0px;
}
#chat-page > div > #main > #task-page .kanban-board-wrapper .kanban-column,
#chat-page > div > #main > #task-page .property-input-wrapper,
#chat-page > div > #main > #task-page .status-grid-wrapper .status-column,
#chat-page > div > #main > #task-page .status-name-row > *,
#chat-page > div > #main > #task-page .status-name-row::before {
width: 18rem;
min-width: 18rem;
max-width: 18rem;
#calendar-page .input-wrapper > input::-webkit-outer-spin-button,
#calendar-page .input-wrapper > input::-webkit-innner-spin-button {
appearance: none;
-webkit-appearance: none;
margin: 0px;
}
#chat-page > div > #main > #task-page .status-name-row,
#chat-page > div > #main > #task-page .status-grid-wrapper {
display: flex;
gap: var(--large-gap);
#chat-page > div > #main > #calendar-page > .pane-wrapper > .pane > .toolbar .input-wrapper > .year-input {
width: 4.4rem;
}
#chat-page > div > #main > #task-page .status-page-content,
#chat-page > div > #main > #task-page .status-grid-wrapper {
flex-direction: column;
}
#chat-page > div > #main > #task-page .status-name-row::before {
content: "";
display: flex;
}
#chat-page > div > #main > #task-page .board-close-button {
display: none;
}
#chat-page > div > #main > #task-page .board-toggle-button {
display: flex;
}
#chat-page > div > #main > #task-page[isshowingboard][showingboardlist=false] #board-list {
display: none;
}
@media (min-width: 640px) {
#chat-page > div > #main > #task-page .task-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
}
#chat-page > div > #main > #calendar-page > .pane-wrapper > .pane > .toolbar .input-wrapper > .month-input {
width: 3.1rem;
}
@media (max-width: 1024px) {
#chat-page > div > #main > #task-page #board-list {
display: false;
#chat-page > div > #main > #calendar-page {
flex-direction: column;
}
#chat-page > div > #main > #task-page #board-content {
display: none;
#chat-page > div > #main > #calendar-page .grid-pane-wrapper {
border-bottom: 1px solid var(--border);
}
#chat-page > div > #main > #task-page[isshowingboard] #board-list {
display: none;
}
/* src/View/Components/monthGrid.css */
.month-grid-wrapper {
display: flex;
flex-direction: column;
gap: var(--gap-between-tiles);
height: 100%;
overflow: auto;
}
.month-grid-wrapper .day-labels {
flex: 0;
padding: var(--content-padding);
padding-bottom: 0px;
}
.month-grid-wrapper > div {
display: grid;
gap: var(--gap-between-tiles);
grid-template-columns: repeat(7, minmax(0px, 1fr));
animation: slide-up var(--animation-duration);
}
.month-grid {
overflow: visible;
padding: var(--content-padding);
padding-top: 0px;
flex: 1;
grid-auto-rows: 1fr;
}
.month-grid .tile {
animation: slide-up var(--animation-duration);
overflow: hidden;
align-items: start;
}
.month-grid .tile[today] b {
color: var(--primary);
}
.month-grid .tile > div {
width: 100%;
height: 100%;
}
.month-grid .tile .event-count {
display: none;
background-color: var(--text-normal);
color: var(--background);
opacity: 0.6;
border-radius: 100%;
width: 1rem;
height: 1rem;
font-size: 0.6rem;
font-weight: bold;
align-items: center;
justify-content: center;
}
.month-grid .tile .event-count[has-events] {
background-color: var(--primary);
opacity: 1;
}
.month-grid .tile .event-list {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
gap: var(--gap-between-tiles);
}
.month-grid .tile .event-list span {
animation: slide-up var(--animation-duration);
}
@media (max-width: 640px) and (max-height: 1200px) {
.month-grid .tile {
padding: 0px;
}
#chat-page > div > #main > #task-page[isshowingboard] #board-content {
.month-grid .tile > div {
align-items: center;
justify-content: center;
}
.month-grid .tile .event-count {
display: flex;
}
#chat-page > div > #main > #task-page .board-close-button {
display: flex;
}
#chat-page > div > #main > #task-page .board-toggle-button {
.month-grid .tile .event-list {
display: none;
}
}
+4289 -4282
View File
File diff suppressed because it is too large Load Diff
+70 -5
View File
@@ -6,10 +6,14 @@
"": {
"dependencies": {
"@types/uuid": "^10.0.0",
"bloatless-react": "^1.3.11",
"esbuild": "^0.23.0",
"bloatless-react": "1.3.14",
"esbuild": "^0.23.1",
"udn-frontend": "^1.0.9",
"uuid": "^10.0.0"
},
"devDependencies": {
"prettier-plugin-organize-imports": "^4.3.0",
"prettier-plugin-sort-imports": "^1.8.11"
}
},
"node_modules/@esbuild/aix-ppc64": {
@@ -403,9 +407,9 @@
"license": "MIT"
},
"node_modules/bloatless-react": {
"version": "1.3.12",
"resolved": "https://registry.npmjs.org/bloatless-react/-/bloatless-react-1.3.12.tgz",
"integrity": "sha512-JEyAA8JKRVuv6swl7TUzOX3vJ9QdV25cQvTqjLyaQlNKfDVPAtLVR8HMfGdpiOC2mr866FghT9OotWKfWd665w==",
"version": "1.3.14",
"resolved": "https://registry.npmjs.org/bloatless-react/-/bloatless-react-1.3.14.tgz",
"integrity": "sha512-Y4v8RnZeggUozvqHsG6QkZI6AvwxtumaJ4NLPQRbCB7/MuuxA2cc6U+Cw4SiXPY1y9TAarI75xOWh8CNK6wijA==",
"license": "SEE LICENSE IN LICENSE",
"dependencies": {
"uuid": "^13.0.0"
@@ -463,6 +467,67 @@
"@esbuild/win32-x64": "0.23.1"
}
},
"node_modules/prettier": {
"version": "3.8.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz",
"integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==",
"dev": true,
"license": "MIT",
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/prettier-plugin-organize-imports": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-4.3.0.tgz",
"integrity": "sha512-FxFz0qFhyBsGdIsb697f/EkvHzi5SZOhWAjxcx2dLt+Q532bAlhswcXGYB1yzjZ69kW8UoadFBw7TyNwlq96Iw==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"prettier": ">=2.0",
"typescript": ">=2.9",
"vue-tsc": "^2.1.0 || 3"
},
"peerDependenciesMeta": {
"vue-tsc": {
"optional": true
}
}
},
"node_modules/prettier-plugin-sort-imports": {
"version": "1.8.11",
"resolved": "https://registry.npmjs.org/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-1.8.11.tgz",
"integrity": "sha512-ApmZkEmNh2Fi6TAcYNgUR15rsP1+omX43+8neY+MXfNZ7JQwrqSdjzKhLUYTtaLo52aaC9gCs+lJaYSU8oSJJA==",
"dev": true,
"license": "MIT",
"dependencies": {
"prettier": "^3.1.1"
},
"peerDependencies": {
"typescript": ">4.0.0"
}
},
"node_modules/typescript": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
"integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/udn-frontend": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/udn-frontend/-/udn-frontend-1.0.9.tgz",
+3
View File
@@ -8,5 +8,8 @@
},
"scripts": {
"build": "esbuild src/index.tsx --bundle --outdir=dist"
},
"devDependencies": {
"prettier-plugin-sort-imports": "^1.8.11"
}
}
+48 -46
View File
@@ -1,64 +1,30 @@
// cleanup: Phase A
import { v4 } from "uuid";
import { Message } from "udn-frontend";
import ChatModel, { ChatMessage } from "./chatModel";
import StorageModel, {
StorageModelSubPaths,
filePaths,
} from "../Global/storageModel";
import ConnectionModel from "../Global/connectionModel";
import { Message } from "udn-frontend";
import SettingsModel from "../Global/settingsModel";
import { v4 } from "uuid";
import ConnectionModel from "../Global/connectionModel";
export default class ChatListModel {
// models
readonly storageModel: StorageModel;
readonly settingsModel: SettingsModel;
readonly connectionModel: ConnectionModel;
// data
chatModels = new Set<ChatModel>();
readonly chatModels = new Set<ChatModel>();
// handlers
messageHandler = (data: Message): void => {
const channel: string | undefined = data.messageChannel;
const body: string | undefined = data.messageBody;
if (channel == undefined) return;
if (body == undefined) return;
this.routeMessageToCorrectChatModel(channel, (chatModel: ChatModel) =>
chatModel.handleMessage(body),
);
};
messageSentHandler = (chatMessage: ChatMessage): void => {
const channel: string = chatMessage.channel;
this.routeMessageToCorrectChatModel(channel, (chatModel: ChatModel) =>
chatModel.handleMessageSent(chatMessage),
);
};
// methods
routeMessageToCorrectChatModel = (
channel: string,
fn: (chatModel: ChatModel) => void,
): void => {
const allChannels: string[] = channel.split("/");
for (const chatModel of this.chatModels) {
for (const channel of allChannels) {
if (channel != chatModel.info.primaryChannel) continue;
fn(chatModel);
break;
}
}
};
// storage
addChatModel = (chatModel: ChatModel) => {
// chat handling
readonly addChatModel = (chatModel: ChatModel) => {
this.chatModels.add(chatModel);
};
createChat = (primaryChannel: string): ChatModel => {
readonly createChat = (primaryChannel: string): ChatModel => {
const id: string = v4();
const chatModel = new ChatModel(
@@ -74,12 +40,48 @@ export default class ChatListModel {
return chatModel;
};
untrackChat = (chat: ChatModel): void => {
readonly untrackChat = (chat: ChatModel): void => {
this.chatModels.delete(chat);
};
// message handlers
readonly messageHandler = (data: Message): void => {
const channel: string | undefined = data.messageChannel;
const body: string | undefined = data.messageBody;
if (channel == undefined) return;
if (body == undefined) return;
this.routeMessageToCorrectChatModel(channel, (chatModel: ChatModel) =>
chatModel.handleMessage(body),
);
};
readonly messageSentHandler = (chatMessage: ChatMessage): void => {
const channel: string = chatMessage.channel;
this.routeMessageToCorrectChatModel(channel, (chatModel: ChatModel) =>
chatModel.handleMessageSent(chatMessage),
);
};
// util
readonly routeMessageToCorrectChatModel = (
channel: string,
fn: (chatModel: ChatModel) => void,
): void => {
const allChannels: string[] = channel.split("/");
for (const chatModel of this.chatModels) {
for (const channel of allChannels) {
if (channel != chatModel.info.primaryChannel) continue;
fn(chatModel);
break;
}
}
};
// load
loadChats = (): void => {
readonly loadChats = (): void => {
const chatDir = StorageModel.getPath(
StorageModelSubPaths.Chat,
filePaths.chat.base,
+46 -44
View File
@@ -1,11 +1,7 @@
// this file is responsible for managing chats.
// cleanup: Phase A
import {
checkMatchesObjectStructure,
DATA_VERSION,
ValidObject,
} from "../Utility/typeSafety";
import FileModel, { FileContent } from "../Files/fileModel";
import { v4 } from "uuid";
import ChatListModel from "./chatListModel";
import {
HandlerManager,
createTimestamp,
@@ -13,24 +9,27 @@ import {
parseValidObject,
stringify,
} from "../Utility/utility";
import {
DATA_VERSION,
ValidObject,
checkMatchesObjectStructure,
} from "../Utility/typeSafety";
import { decryptString, encryptString } from "../Utility/crypto";
import StorageModel, {
StorageModelSubPaths,
filePaths,
} from "../Global/storageModel";
import { decryptString, encryptString } from "../Utility/crypto";
import ChatListModel from "./chatListModel";
import { Colors } from "../../colors";
import ConnectionModel from "../Global/connectionModel";
import SettingsModel from "../Global/settingsModel";
import { v4 } from "uuid";
import ConnectionModel from "../Global/connectionModel";
import FileModel, { FileContent } from "../Files/fileModel";
import { Colors } from "../../colors";
export default class ChatModel {
// models
readonly connectionModel: ConnectionModel;
readonly storageModel: StorageModel;
readonly settingsModel: SettingsModel;
readonly chatListModel: ChatListModel;
readonly fileModel: FileModel;
// data
@@ -38,61 +37,62 @@ export default class ChatModel {
info: ChatInfo;
color: Colors;
get secondaryChannels(): string[] {
return this.info.secondaryChannels.sort(localeCompare);
}
// handler managers
chatMessageHandlerManager: HandlerManager<ChatMessage> =
new HandlerManager();
readonly reactionHandlerManager: HandlerManager<ChatMessageReaction> =
new HandlerManager();
get secondaryChannels(): string[] {
return this.info.secondaryChannels.sort(localeCompare);
}
// paths
getBasePath = (): string[] => {
readonly getBasePath = (): string[] => {
return StorageModel.getPath(
StorageModelSubPaths.Chat,
filePaths.chat.chatBase(this.id),
);
};
getInfoPath = (): string[] => {
readonly getInfoPath = (): string[] => {
return StorageModel.getPath(
StorageModelSubPaths.Chat,
filePaths.chat.info(this.id),
);
};
getColorPath = (): string[] => {
readonly getColorPath = (): string[] => {
return StorageModel.getPath(
StorageModelSubPaths.Chat,
filePaths.chat.color(this.id),
);
};
getMessageDirPath = (): string[] => {
readonly getMessageDirPath = (): string[] => {
return StorageModel.getPath(
StorageModelSubPaths.Chat,
filePaths.chat.messages(this.id),
);
};
getMessagePath = (id: string): string[] => {
readonly getMessagePath = (id: string): string[] => {
return [...this.getMessageDirPath(), id];
};
getReactionDirPath = (): string[] => {
readonly getReactionDirPath = (): string[] => {
return StorageModel.getPath(
StorageModelSubPaths.Chat,
filePaths.chat.reactions(this.id),
);
};
getReactionPath = (id: string): string[] => {
readonly getReactionPath = (id: string): string[] => {
return [...this.getReactionDirPath(), id];
};
// handlers
handleMessage = (body: string): void => {
readonly handleMessage = (body: string): void => {
const chatMessage: ChatMessage | null = parseValidObject(
body,
ChatMessageReference,
@@ -107,7 +107,7 @@ export default class ChatModel {
this.setReadStatus(true);
};
handleReaction = (reaction: ChatMessageReaction | any): void => {
readonly handleReaction = (reaction: ChatMessageReaction | any): void => {
if (
!checkMatchesObjectStructure(reaction, ChatMessageReactionReference)
)
@@ -122,35 +122,35 @@ export default class ChatModel {
this.reactionHandlerManager.trigger(reaction);
};
handleMessageSent = (chatMessage: ChatMessage): void => {
readonly handleMessageSent = (chatMessage: ChatMessage): void => {
chatMessage.status = ChatMessageStatuses.Sent;
this.addMessage(chatMessage);
};
// settings
setPrimaryChannel = (primaryChannel: string): void => {
readonly setPrimaryChannel = (primaryChannel: string): void => {
this.info.primaryChannel = primaryChannel;
this.storeInfo();
this.subscribe();
};
setSecondaryChannels = (secondaryChannels: string[]): void => {
readonly setSecondaryChannels = (secondaryChannels: string[]): void => {
this.info.secondaryChannels = secondaryChannels;
this.storeInfo();
};
setEncryptionKey = (key: string): void => {
readonly setEncryptionKey = (key: string): void => {
this.info.encryptionKey = key;
this.storeInfo();
};
setColor = (color: Colors): void => {
readonly setColor = (color: Colors): void => {
this.color = color;
this.storeColor();
};
// messaging
addMessage = async (chatMessage: ChatMessage): Promise<void> => {
readonly addMessage = async (chatMessage: ChatMessage): Promise<void> => {
await this.decryptMessage(chatMessage);
// message
@@ -166,7 +166,7 @@ export default class ChatModel {
);
};
getNameAndChannel = (): [string, string] | false => {
readonly getNameAndChannel = (): [string, string] | false => {
const senderName: string = this.settingsModel.username;
if (senderName == "") return false;
@@ -180,7 +180,7 @@ export default class ChatModel {
return [senderName, combinedChannel];
};
sendMessage = async (
readonly sendMessage = async (
body: string,
inlineReplyId?: string,
fileContent?: FileContent<string>,
@@ -203,7 +203,9 @@ export default class ChatModel {
return true;
};
decryptMessage = async (chatMessage: ChatMessage): Promise<void> => {
readonly decryptMessage = async (
chatMessage: ChatMessage,
): Promise<void> => {
const decryptedBody: string = await decryptString(
chatMessage.body,
this.info.encryptionKey,
@@ -216,7 +218,7 @@ export default class ChatModel {
chatMessage.stringifiedFile = decryptedFile;
};
sendReaction = async (
readonly sendReaction = async (
messageId: string,
content: ReactionSymbols,
isDeleting?: boolean,
@@ -235,25 +237,25 @@ export default class ChatModel {
this.handleReaction(reaction);
};
subscribe = (): void => {
readonly subscribe = (): void => {
this.connectionModel.addChannel(this.info.primaryChannel);
};
setReadStatus = (hasUnreadMessages: boolean): void => {
readonly setReadStatus = (hasUnreadMessages: boolean): void => {
this.info.hasUnreadMessages = hasUnreadMessages;
this.storeInfo();
};
// storage
storeInfo = (): void => {
readonly storeInfo = (): void => {
this.storageModel.writeStringifiable(this.getInfoPath(), this.info);
};
storeColor = (): void => {
readonly storeColor = (): void => {
this.storageModel.write(this.getColorPath(), this.color);
};
delete = () => {
readonly delete = () => {
// untrack
this.chatListModel.untrackChat(this);
@@ -263,7 +265,7 @@ export default class ChatModel {
};
// load
loadInfo = (): void => {
readonly loadInfo = (): void => {
const info: ChatInfo | null = this.storageModel.readStringifiable(
this.getInfoPath(),
ChatInfoReference,
@@ -275,7 +277,7 @@ export default class ChatModel {
}
};
loadColor = (): void => {
readonly loadColor = (): void => {
const path: string[] = this.getColorPath();
const color: string | null = this.storageModel.read(path);
if (!color) {
+36 -37
View File
@@ -1,18 +1,17 @@
// this file is responsible for managing boards within chats and tasks within boards.
// cleanup: Phase A
import { v4 } from "uuid";
import FileModel, { FileContent, FileModelSubPath } from "./fileModel";
import CalendarModel from "./calendarModel";
import { HandlerManager } from "../Utility/utility";
import {
DATA_VERSION,
checkMatchesObjectStructure,
} from "../Utility/typeSafety";
import FileModel, { FileContent, FileModelSubPath } from "./fileModel";
import CalendarModel from "./calendarModel";
import StorageModel from "../Global/storageModel";
import SettingsModel from "../Global/settingsModel";
import ChatModel from "../Chat/chatModel";
import { Colors } from "../../colors";
import { HandlerManager } from "../Utility/utility";
import SettingsModel from "../Global/settingsModel";
import StorageModel from "../Global/storageModel";
import { v4 } from "uuid";
export default class BoardsAndTasksModel {
readonly storageModel: StorageModel;
@@ -27,43 +26,43 @@ export default class BoardsAndTasksModel {
readonly taskHandlerManager = new HandlerManager<TaskFileContent>();
// paths
getBasePath = (): string[] => {
readonly getBasePath = (): string[] => {
return this.fileModel.getModelContainerPath(FileModelSubPath.ModelTask);
};
getViewPath = (): string[] => {
readonly getViewPath = (): string[] => {
return [...this.getBasePath(), FileModelSubPath.ModelView];
};
getBoardFilePath = (boardId: string): string[] => {
readonly getBoardFilePath = (boardId: string): string[] => {
return [...this.fileModel.getFilePath(boardId)];
};
getTaskFilePath = (taskId: string): string[] => {
readonly getTaskFilePath = (taskId: string): string[] => {
return [...this.fileModel.getFilePath(taskId)];
};
getBoardContainerPath = (): string[] => {
readonly getBoardContainerPath = (): string[] => {
return [...this.getBasePath(), TaskModelSubPaths.Boards];
};
getBoardDirectoryPath = (boardId: string): string[] => {
readonly getBoardDirectoryPath = (boardId: string): string[] => {
return [...this.getBoardContainerPath(), boardId];
};
getTaskContainerPath = (boardId: string): string[] => {
readonly getTaskContainerPath = (boardId: string): string[] => {
return [
...this.getBoardDirectoryPath(boardId),
TaskModelSubPaths.BoardTasks,
];
};
getTaskReferencePath = (boardId: string, fileId: string): string[] => {
readonly getTaskReferencePath = (boardId: string, fileId: string): string[] => {
return [...this.getTaskContainerPath(boardId), fileId];
};
// handlers
handleFileContent = (fileContent: FileContent<string>): void => {
readonly handleFileContent = (fileContent: FileContent<string>): void => {
if (
checkMatchesObjectStructure(
fileContent,
@@ -81,16 +80,16 @@ export default class BoardsAndTasksModel {
}
};
handleBoard = (boardInfoFileContent: BoardInfoFileContent) => {
readonly handleBoard = (boardInfoFileContent: BoardInfoFileContent) => {
this.updateBoard(boardInfoFileContent);
};
handleTask = (taskFileContent: TaskFileContent) => {
readonly handleTask = (taskFileContent: TaskFileContent) => {
this.updateTask(taskFileContent);
};
// boards
createBoard = (name: string): BoardInfoFileContent => {
readonly createBoard = (name: string): BoardInfoFileContent => {
const boardInfoFileContent: BoardInfoFileContent =
BoardsAndTasksModel.createBoardInfoFileContent(
v4(),
@@ -100,17 +99,17 @@ export default class BoardsAndTasksModel {
return boardInfoFileContent;
};
updateBoard = (boardInfoFileContent: BoardInfoFileContent): void => {
readonly updateBoard = (boardInfoFileContent: BoardInfoFileContent): void => {
this.storeBoard(boardInfoFileContent);
this.boardHandlerManager.trigger(boardInfoFileContent);
};
updateBoardAndSend = (boardInfoFileContent: BoardInfoFileContent): void => {
readonly updateBoardAndSend = (boardInfoFileContent: BoardInfoFileContent): void => {
this.updateBoard(boardInfoFileContent);
this.chatModel.sendMessage("", undefined, boardInfoFileContent);
};
storeBoard = (boardInfoFileContent: BoardInfoFileContent): void => {
readonly storeBoard = (boardInfoFileContent: BoardInfoFileContent): void => {
// store info
this.fileModel.storeFileContent(boardInfoFileContent);
@@ -121,7 +120,7 @@ export default class BoardsAndTasksModel {
this.storageModel.write(boardDirectoryPath, "");
};
deleteBoard = (boardId: string): void => {
readonly deleteBoard = (boardId: string): void => {
const boardFilePath: string[] = this.getBoardFilePath(boardId);
const boardDirectoryPath: string[] =
this.getBoardDirectoryPath(boardId);
@@ -130,13 +129,13 @@ export default class BoardsAndTasksModel {
this.storageModel.removeRecursively(boardDirectoryPath);
};
listBoardIds = (): string[] => {
readonly listBoardIds = (): string[] => {
const boardContainerPath: string[] = this.getBoardContainerPath();
const boardIds: string[] = this.storageModel.list(boardContainerPath);
return boardIds;
};
getBoardInfo = (fileId: string): BoardInfoFileContent | null => {
readonly getBoardInfo = (fileId: string): BoardInfoFileContent | null => {
const boardInfoFileContentOrNull: BoardInfoFileContent | null =
this.fileModel.getLatestFileContent(
fileId,
@@ -145,7 +144,7 @@ export default class BoardsAndTasksModel {
return boardInfoFileContentOrNull;
};
getBoardName = (boardId: string): string => {
readonly getBoardName = (boardId: string): string => {
const boardInfo: BoardInfoFileContent | null =
this.getBoardInfo(boardId);
if (boardInfo == null) return "";
@@ -153,23 +152,23 @@ export default class BoardsAndTasksModel {
};
//tasks
createTask = (boardId: string): TaskFileContent => {
readonly createTask = (boardId: string): TaskFileContent => {
const taskFileContent: TaskFileContent =
BoardsAndTasksModel.createTaskFileContent(v4(), "", boardId);
return taskFileContent;
};
updateTask = (taskFileContent: TaskFileContent): void => {
readonly updateTask = (taskFileContent: TaskFileContent): void => {
this.storeTask(taskFileContent);
this.taskHandlerManager.trigger(taskFileContent);
};
updateTaskAndSend = (taskFileContent: TaskFileContent): void => {
readonly updateTaskAndSend = (taskFileContent: TaskFileContent): void => {
this.updateTask(taskFileContent);
this.chatModel.sendMessage("", undefined, taskFileContent);
};
storeTask = (taskFileContent: TaskFileContent): void => {
readonly storeTask = (taskFileContent: TaskFileContent): void => {
// store info
this.fileModel.storeFileContent(taskFileContent);
@@ -184,18 +183,18 @@ export default class BoardsAndTasksModel {
this.calendarModel.storeTaskReference(taskFileContent);
};
listTaskIds = (boardId: string): string[] => {
readonly listTaskIds = (boardId: string): string[] => {
const taskContainerPath: string[] = this.getTaskContainerPath(boardId);
const fileIds: string[] = this.storageModel.list(taskContainerPath);
return fileIds;
};
listTaskVersionIds = (taskId: string): string[] => {
readonly listTaskVersionIds = (taskId: string): string[] => {
const versionIds: string[] = this.fileModel.listFileContentIds(taskId);
return versionIds;
};
getLatestTaskFileContent = (taskId: string): TaskFileContent | null => {
readonly getLatestTaskFileContent = (taskId: string): TaskFileContent | null => {
const taskFileContentOrNull: TaskFileContent | null =
this.fileModel.getLatestFileContent(
taskId,
@@ -204,7 +203,7 @@ export default class BoardsAndTasksModel {
return taskFileContentOrNull;
};
getSpecificTaskFileContent = (
readonly getSpecificTaskFileContent = (
taskId: string,
versionId: string,
): TaskFileContent | null => {
@@ -217,14 +216,14 @@ export default class BoardsAndTasksModel {
return taskFileContentOrNull;
};
deleteTask = (boardId: string, taskId: string): void => {
readonly deleteTask = (boardId: string, taskId: string): void => {
const taskFilePath: string[] = this.getTaskFilePath(taskId);
this.storageModel.removeRecursively(taskFilePath);
this.deleteTaskReference(boardId, taskId);
};
deleteTaskReference = (boardId: string, taskId: string): void => {
readonly deleteTaskReference = (boardId: string, taskId: string): void => {
const taskReferencePath: string[] = this.getTaskReferencePath(
boardId,
taskId,
+16 -15
View File
@@ -1,10 +1,9 @@
// it is responsible for managing calendar-realted reference files for tasks.
// cleanup: Phase A
import FileModel, { FileModelSubPath } from "./fileModel";
import SettingsModel from "../Global/settingsModel";
import StorageModel from "../Global/storageModel";
import { TaskFileContent } from "./boardsAndTasksModel";
import StorageModel from "../Global/storageModel";
import SettingsModel from "../Global/settingsModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
export default class CalendarModel {
@@ -13,26 +12,26 @@ export default class CalendarModel {
readonly settingsModel: SettingsModel;
// paths
getBasePath = (): string[] => {
get basePath (): string[] {
return this.fileModel.getModelContainerPath(
FileModelSubPath.ModelCalendar,
);
};
getViewPath = (): string[] => {
return [...this.getBasePath(), FileModelSubPath.ModelView];
readonly getViewPath = (): string[] => {
return [...this.basePath, FileModelSubPath.ModelView];
};
getMonthContainerPath = (): string[] => {
return [...this.getBasePath(), CalendarModelSubPaths.Months];
readonly getMonthContainerPath = (): string[] => {
return [...this.basePath, CalendarModelSubPaths.Months];
};
getMonthPath = (monthString: string): string[] => {
readonly getMonthPath = (monthString: string): string[] => {
return [...this.getMonthContainerPath(), monthString];
};
// main
storeTaskReference = (taskFileContent: TaskFileContent): void => {
// task references
readonly storeTaskReference = (taskFileContent: TaskFileContent): void => {
if (taskFileContent.date == undefined) return;
const monthString: string = CalendarModel.isoToMonthString(
@@ -45,19 +44,21 @@ export default class CalendarModel {
this.storageModel.write(referencePath, "");
};
deleteTaskReference = (monthString: string, taskId: string): void => {
readonly deleteTaskReference = (monthString: string, taskId: string): void => {
const monthPath: string[] = this.getMonthPath(monthString);
const referencePath: string[] = [...monthPath, taskId];
this.storageModel.write(referencePath, "");
};
listTaskIds = (monthString: string): string[] => {
// data
readonly listTaskIds = (monthString: string): string[] => {
const monthPath: string[] = this.getMonthPath(monthString);
return this.storageModel.list(monthPath);
};
generateMonthGrid = <T>(
// util
readonly generateMonthGrid = <T>(
coreViewModel: CoreViewModel,
year: number,
month: number,
+26 -27
View File
@@ -1,21 +1,20 @@
// this file is responsible for managing files within chats.
// cleanup: Phase A
import { DATA_VERSION, ValidObject } from "../Utility/typeSafety";
import StorageModel, {
StorageModelSubPaths,
filePaths,
} from "../Global/storageModel";
import { v4 } from "uuid";
import BoardsAndTasksModel from "./boardsAndTasksModel";
import {
StringEntryObject,
createTimestamp,
parseValidObject,
stringify,
} from "../Utility/utility";
import BoardsAndTasksModel from "./boardsAndTasksModel";
import ChatModel from "../Chat/chatModel";
import { DATA_VERSION, ValidObject } from "../Utility/typeSafety";
import StorageModel, {
StorageModelSubPaths,
filePaths,
} from "../Global/storageModel";
import SettingsModel from "../Global/settingsModel";
import { v4 } from "uuid";
import ChatModel from "../Chat/chatModel";
export default class FileModel {
readonly storageModel: StorageModel;
@@ -25,32 +24,32 @@ export default class FileModel {
readonly boardsAndTasksModel: BoardsAndTasksModel;
// paths
getBasePath = (): string[] => {
get basePath(): string[] {
return StorageModel.getPath(
StorageModelSubPaths.Chat,
filePaths.chat.files(this.chatModel.id),
);
};
getFileContainerPath = (): string[] => {
return [...this.getBasePath(), FileModelSubPath.Data];
readonly getFileContainerPath = (): string[] => {
return [...this.basePath, FileModelSubPath.Data];
};
getModelContainerPath = (modelName: FileModelSubPath): string[] => {
return [...this.getBasePath(), FileModelSubPath.Model, modelName];
readonly getModelContainerPath = (modelName: FileModelSubPath): string[] => {
return [...this.basePath, FileModelSubPath.Model, modelName];
};
getFilePath = (fileId: string): string[] => {
readonly getFilePath = (fileId: string): string[] => {
return [...this.getFileContainerPath(), fileId];
};
getFileContentPath = (fileId: string, fileContentId: string): string[] => {
readonly getFileContentPath = (fileId: string, fileContentId: string): string[] => {
const filePath: string[] = this.getFilePath(fileId);
return [...filePath, fileContentId];
};
// handlers
handleStringifiedFileContent = (stringifiedFileContent: string): void => {
readonly handleStringifiedFileContent = (stringifiedFileContent: string): void => {
const fileContent: FileContent<string> | null = parseValidObject(
stringifiedFileContent,
FileContentReference,
@@ -60,7 +59,7 @@ export default class FileModel {
this.handleFileContent(fileContent);
};
handleFileContent = (fileContent: FileContent<string>): void => {
readonly handleFileContent = (fileContent: FileContent<string>): void => {
const didStore: boolean = this.storeFileContent(fileContent);
if (didStore == false) return;
@@ -69,13 +68,13 @@ export default class FileModel {
};
// methods
addFileContentAndSend = (fileContent: FileContent<string>): void => {
readonly addFileContentAndSend = (fileContent: FileContent<string>): void => {
this.handleFileContent(fileContent);
this.chatModel.sendMessage("", undefined, fileContent);
};
// storage
storeFileContent = (fileContent: FileContent<string>): boolean => {
readonly storeFileContent = (fileContent: FileContent<string>): boolean => {
const fileContentPath: string[] = this.getFileContentPath(
fileContent.fileId,
fileContent.fileContentId,
@@ -91,22 +90,22 @@ export default class FileModel {
return true;
};
listFileIds = (): string[] => {
return this.storageModel.list(this.getBasePath());
readonly listFileIds = (): string[] => {
return this.storageModel.list(this.basePath);
};
listFileContentIds = (fileId: string): string[] => {
readonly listFileContentIds = (fileId: string): string[] => {
const filePath: string[] = this.getFilePath(fileId);
return this.storageModel.list(filePath);
};
selectLatestFileContentId = (
readonly selectLatestFileContentId = (
fileContentIds: string[],
): string | undefined => {
return fileContentIds[fileContentIds.length - 1];
};
getFileContent = <T extends FileContent<string>>(
readonly getFileContent = <T extends FileContent<string>>(
fileId: string,
fileContentName: string,
reference: T,
@@ -122,7 +121,7 @@ export default class FileModel {
return fileContentOrNull;
};
getLatestFileContent = <T extends FileContent<string>>(
readonly getLatestFileContent = <T extends FileContent<string>>(
fileId: string,
reference: T,
): T | null => {
+32 -28
View File
@@ -1,13 +1,16 @@
// this file is responsible for managing UDN connections.
// cleanup: Phase A
import { ChatMessage, ChatMessageReference } from "../Chat/chatModel";
import { HandlerManager, stringify } from "../Utility/utility";
import StorageModel, { StorageModelSubPaths, filePaths } from "./storageModel";
import UDNFrontend, { Message } from "udn-frontend";
import StorageModel, { StorageModelSubPaths, filePaths } from "./storageModel";
import { HandlerManager, stringify } from "../Utility/utility";
import { ChatMessage, ChatMessageReference } from "../Chat/chatModel";
export default class ConnectionModel {
// models etc
readonly udn: UDNFrontend;
readonly storageModel: StorageModel;
// config
reconnectInterval: number | undefined = undefined;
shouldAttemptReconnect: boolean = false;
@@ -20,17 +23,18 @@ export default class ConnectionModel {
return this.udn.ws?.url;
}
// handler managers
readonly connectionChangeHandlerManager = new HandlerManager<void>();
readonly messageHandlerManager = new HandlerManager<Message>();
readonly messageSentHandlerManager = new HandlerManager<ChatMessage>();
readonly channelsToSubscribe = new Set<string>();
// handlers
handleMessage = (data: Message): void => {
readonly handleMessage = (data: Message): void => {
this.messageHandlerManager.trigger(data);
};
handleConnectionChange = (): void => {
readonly handleConnectionChange = (): void => {
console.log("connection status:", this.isConnected, this.address);
this.connectionChangeHandlerManager.trigger();
if (this.address == undefined) return;
@@ -41,13 +45,13 @@ export default class ConnectionModel {
};
// connection
connect = (address: string): void => {
readonly connect = (address: string): void => {
console.log("connecting...", address);
this.shouldAttemptReconnect = true;
this.udn.connect(address);
};
disconnect = (): void => {
readonly disconnect = (): void => {
this.shouldAttemptReconnect = false;
this.udn.disconnect();
@@ -59,7 +63,7 @@ export default class ConnectionModel {
this.storageModel.remove(reconnectAddressPath);
};
reconnect = (): void => {
readonly reconnect = (): void => {
const reconnectAddressPath: string[] = this.getReconnectAddressPath();
const reconnectAddress: string | null =
this.storageModel.read(reconnectAddressPath);
@@ -70,7 +74,7 @@ export default class ConnectionModel {
};
// mailbox
getMailboxPath = (address: string): string[] => {
readonly getMailboxPath = (address: string): string[] => {
const mailboxDirPath = StorageModel.getPath(
StorageModelSubPaths.ConnectionModel,
filePaths.connectionModel.mailboxes,
@@ -79,12 +83,12 @@ export default class ConnectionModel {
return mailboxFilePath;
};
requestNewMailbox = (): void => {
readonly requestNewMailbox = (): void => {
console.log("requesting new mailbox");
this.udn.requestMailbox();
};
connectMailbox = (): void => {
readonly connectMailbox = (): void => {
if (this.address == undefined) return;
const mailboxId = this.storageModel.read(
@@ -96,18 +100,18 @@ export default class ConnectionModel {
this.udn.connectMailbox(mailboxId);
};
storeMailbox = (mailboxId: string): void => {
readonly storeMailbox = (mailboxId: string): void => {
if (this.address == undefined) return;
this.storageModel.write(this.getMailboxPath(this.address), mailboxId);
};
// subscription
addChannel = (channel: string): void => {
readonly addChannel = (channel: string): void => {
this.channelsToSubscribe.add(channel);
this.sendSubscriptionRequest();
};
sendSubscriptionRequest = (): void => {
readonly sendSubscriptionRequest = (): void => {
if (this.isConnected == false) return;
for (const channel of this.channelsToSubscribe) {
@@ -118,14 +122,14 @@ export default class ConnectionModel {
};
// outbox
getOutboxPath = (): string[] => {
readonly getOutboxPath = (): string[] => {
return StorageModel.getPath(
StorageModelSubPaths.ConnectionModel,
filePaths.connectionModel.outbox,
);
};
getOutboxMessags = (): ChatMessage[] => {
readonly getOutboxMessags = (): ChatMessage[] => {
const outboxPath: string[] = this.getOutboxPath();
const messageIds: string[] = this.storageModel.list(outboxPath);
@@ -144,17 +148,17 @@ export default class ConnectionModel {
return chatMessages;
};
addToOutbox = (chatMessage: ChatMessage): void => {
readonly addToOutbox = (chatMessage: ChatMessage): void => {
const messagePath: string[] = [...this.getOutboxPath(), chatMessage.id];
this.storageModel.writeStringifiable(messagePath, chatMessage);
};
removeFromOutbox = (chatMessage: ChatMessage): void => {
readonly removeFromOutbox = (chatMessage: ChatMessage): void => {
const messagePath: string[] = [...this.getOutboxPath(), chatMessage.id];
this.storageModel.remove(messagePath);
};
sendMessagesInOutbox = (): void => {
readonly sendMessagesInOutbox = (): void => {
const messages: ChatMessage[] = this.getOutboxMessags();
for (const message of messages) {
@@ -166,14 +170,14 @@ export default class ConnectionModel {
};
// messaging
sendMessageOrStore = (chatMessage: ChatMessage): void => {
readonly sendMessageOrStore = (chatMessage: ChatMessage): void => {
const isSent = this.tryToSendMessage(chatMessage);
if (isSent == true) return;
this.addToOutbox(chatMessage);
};
tryToSendMessage = (chatMessage: ChatMessage): boolean => {
readonly tryToSendMessage = (chatMessage: ChatMessage): boolean => {
const stringifiedBody: string = stringify(chatMessage);
const isSent: boolean = this.sendPlainMessage(
chatMessage.channel,
@@ -183,31 +187,31 @@ export default class ConnectionModel {
return isSent;
};
sendPlainMessage = (channel: string, body: string): boolean => {
readonly sendPlainMessage = (channel: string, body: string): boolean => {
return this.udn.sendMessage(channel, body);
};
// storage
getPreviousAddressPath = (): string[] => {
readonly getPreviousAddressPath = (): string[] => {
return StorageModel.getPath(
StorageModelSubPaths.ConnectionModel,
filePaths.connectionModel.previousAddresses,
);
};
getAddressPath = (address: string): string[] => {
readonly getAddressPath = (address: string): string[] => {
const dirPath = this.getPreviousAddressPath();
return [...dirPath, address];
};
getReconnectAddressPath = (): string[] => {
readonly getReconnectAddressPath = (): string[] => {
return StorageModel.getPath(
StorageModelSubPaths.ConnectionModel,
filePaths.connectionModel.reconnectAddress,
);
};
storeAddress = (address: string): void => {
readonly storeAddress = (address: string): void => {
// history
const addressPath = this.getAddressPath(address);
this.storageModel.write(addressPath, "");
@@ -217,7 +221,7 @@ export default class ConnectionModel {
this.storageModel.write(reconnectAddressPath, address);
};
removeAddress = (address: string): void => {
readonly removeAddress = (address: string): void => {
const addressPath = this.getAddressPath(address);
this.storageModel.remove(addressPath);
};
+16 -15
View File
@@ -1,17 +1,16 @@
// this file is responsible for sending and handling files.
// cleanup: Phase A
import { Message } from "udn-frontend";
import StorageModel from "./storageModel";
import ConnectionModel from "./connectionModel";
import {
HandlerManager,
generateRandomToken,
parse,
stringify,
} from "../Utility/utility";
import { decryptString, encryptString } from "../Utility/crypto";
import ConnectionModel from "./connectionModel";
import { Message } from "udn-frontend";
import StorageModel from "./storageModel";
import { checkMatchesObjectStructure } from "../Utility/typeSafety";
import { decryptString, encryptString } from "../Utility/crypto";
export default class FileTransferModel {
readonly storageModel: StorageModel;
@@ -21,12 +20,14 @@ export default class FileTransferModel {
// data
transferData: TransferData | undefined;
readonly fileHandlerManager = new HandlerManager<string>();
readonly readyToSendHandlerManager = new HandlerManager<boolean>();
direction: TransferDirections = TransferDirections.Send;
// handler managers
readonly fileHandlerManager = new HandlerManager<string>();
readonly readyToSendHandlerManager = new HandlerManager<boolean>();
// general
generateTransferData = (): TransferData => {
readonly generateTransferData = (): TransferData => {
const transferData: TransferData = {
channel: generateRandomToken(4),
key: generateRandomToken(6),
@@ -35,12 +36,12 @@ export default class FileTransferModel {
return transferData;
};
prepareToSend = (): void => {
readonly prepareToSend = (): void => {
this.direction = TransferDirections.Send;
this.connectionModel.addChannel(this.transferData.channel);
};
prepareToReceive = (transferData: TransferData): void => {
readonly prepareToReceive = (transferData: TransferData): void => {
this.direction = TransferDirections.Receive;
this.connectionModel.addChannel(transferData.channel);
@@ -52,7 +53,7 @@ export default class FileTransferModel {
};
// handlers
handleMessage = (data: Message): void => {
readonly handleMessage = (data: Message): void => {
if (this.transferData == undefined) return;
if (data.messageChannel != this.transferData.channel) return;
if (
@@ -68,7 +69,7 @@ export default class FileTransferModel {
this.handleFile(data.messageBody);
};
handleFile = async (encryptedFileData: string): Promise<void> => {
readonly handleFile = async (encryptedFileData: string): Promise<void> => {
if (this.transferData == undefined) return;
const decrypted: string = await decryptString(
@@ -93,7 +94,7 @@ export default class FileTransferModel {
};
// sending
sendFiles = (
readonly sendFiles = (
directoryPaths: IteratorObject<string[]>,
callback: (path: string) => void,
): void => {
@@ -108,7 +109,7 @@ export default class FileTransferModel {
}
};
sendFile = async (filePath: string[]): Promise<void> => {
readonly sendFile = async (filePath: string[]): Promise<void> => {
if (this.transferData == undefined) return;
const fileContent: string | null = this.storageModel.read(filePath);
if (fileContent == null) return;
+12 -12
View File
@@ -1,4 +1,4 @@
// this file is responsible for all settings.
// cleanup: Phase A
import StorageModel, { StorageModelSubPaths, filePaths } from "./storageModel";
@@ -12,10 +12,10 @@ export default class SettingsModel {
theme: string;
// storage
private storeSetting(
private readonly storeSetting = (
pathName: keyof typeof filePaths.settingsModel,
value: string,
): void {
): void => {
const path = StorageModel.getPath(
StorageModelSubPaths.SettingsModel,
filePaths.settingsModel[pathName],
@@ -23,28 +23,28 @@ export default class SettingsModel {
this.storageModel.write(path, value);
}
setName = (newValue: string): void => {
readonly setName = (newValue: string): void => {
this.username = newValue;
this.storeSetting("username", newValue);
};
setFirstDayOfWeek = (newValue: string): void => {
readonly setFirstDayOfWeek = (newValue: string): void => {
this.firstDayOfWeek = newValue;
this.storeSetting("firstDayOfWeek", newValue);
};
setLanguage = (newValue: string): void => {
readonly setLanguage = (newValue: string): void => {
this.language = newValue;
this.storeSetting("language", newValue);
};
setTheme = (newValue: string): void => {
readonly setTheme = (newValue: string): void => {
this.theme = newValue;
this.storeSetting("theme", newValue);
};
// load
private readSetting = (
private readonly readSetting = (
pathName: keyof typeof filePaths.settingsModel,
): string => {
const path = StorageModel.getPath(
@@ -54,22 +54,22 @@ export default class SettingsModel {
return this.storageModel.read(path);
};
loadUsername = (): void => {
readonly loadUsername = (): void => {
const content: string | null = this.readSetting("username");
this.username = content ?? "";
};
loadFirstDayofWeek = (): void => {
readonly loadFirstDayofWeek = (): void => {
const content: string | null = this.readSetting("firstDayOfWeek");
this.firstDayOfWeek = content ?? "0";
};
loadLanguage = (): void => {
readonly loadLanguage = (): void => {
const content: string | null = this.readSetting("language");
this.language = content ?? SettingsModel.getSystemLanguage();
};
loadTheme = (): void => {
readonly loadTheme = (): void => {
const content: string | null = this.readSetting("theme");
this.theme = content ?? ThemeSettings.System;
};
+16 -16
View File
@@ -1,7 +1,7 @@
// this file is responsible for reading and writing persistent data.
// cleanup: Phase A
import { DATA_VERSION, ValidObject } from "../Utility/typeSafety";
import { localeCompare, parseValidObject, stringify } from "../Utility/utility";
import { DATA_VERSION, ValidObject } from "../Utility/typeSafety";
export const PATH_COMPONENT_SEPARATOR = "\\";
@@ -9,14 +9,14 @@ export default class StorageModel {
storageEntryTree: StorageEntry = {};
// read
read = (pathComponents: string[]): string | null => {
readonly read = (pathComponents: string[]): string | null => {
const pathString: string = StorageModel.pathComponentsToString(
...pathComponents,
);
return localStorage.getItem(pathString);
};
list = (pathComponents: string[]): string[] => {
readonly list = (pathComponents: string[]): string[] => {
let currentParent: StorageEntry = this.storageEntryTree;
for (const component of pathComponents) {
const nextParent: StorageEntry | undefined =
@@ -29,7 +29,7 @@ export default class StorageModel {
};
// write
write = (pathComponents: string[], value: string): void => {
readonly write = (pathComponents: string[], value: string): void => {
const pathString: string = StorageModel.pathComponentsToString(
...pathComponents,
);
@@ -37,7 +37,7 @@ export default class StorageModel {
this.updateTree(...pathComponents);
};
remove = (
readonly remove = (
pathComponents: string[],
shouldInitialize: boolean = true,
): void => {
@@ -51,7 +51,7 @@ export default class StorageModel {
}
};
rename = (
readonly rename = (
sourcePathComponents: string[],
destinationPathComponents: string[],
shouldInitialize: boolean = true,
@@ -69,7 +69,7 @@ export default class StorageModel {
};
// recursion
recurse = (rootDirectory: string[], fn: (path: string[]) => void): void => {
readonly recurse = (rootDirectory: string[], fn: (path: string[]) => void): void => {
loop_over_files: for (const key of Object.keys(localStorage)) {
// get path of current entity
const pathComponentsOfCurrentEntity: string[] =
@@ -92,14 +92,14 @@ export default class StorageModel {
this.initializeTree();
};
removeRecursively = (pathComponents: string[]): void => {
readonly removeRecursively = (pathComponents: string[]): void => {
this.recurse(pathComponents, (path: string[]) =>
this.remove(path, false),
);
this.initializeTree();
};
renameRecursively = (
readonly renameRecursively = (
sourcePathComponents: string[],
destinationPathComponents: string[],
): void => {
@@ -120,7 +120,7 @@ export default class StorageModel {
};
// stringifiable
writeStringifiable = (
readonly writeStringifiable = (
pathComponents: string[],
value: ValidObject,
): void => {
@@ -128,7 +128,7 @@ export default class StorageModel {
this.write(pathComponents, valueString);
};
readStringifiable = <T extends ValidObject>(
readonly readStringifiable = <T extends ValidObject>(
pathComponents: string[],
reference: T,
): T | null => {
@@ -142,7 +142,7 @@ export default class StorageModel {
};
// cleaning
removeJunk = (): void => {
readonly removeJunk = (): void => {
this.recurse([], (path: string[]) => {
if (path[0] == DATA_VERSION) return;
this.remove(path);
@@ -150,7 +150,7 @@ export default class StorageModel {
};
// tree
initializeTree = (): void => {
readonly initializeTree = (): void => {
console.log("initializing tree");
this.storageEntryTree = {};
@@ -161,7 +161,7 @@ export default class StorageModel {
}
};
updateTree = (...pathComponents: string[]): void => {
readonly updateTree = (...pathComponents: string[]): void => {
let currentParent: StorageEntry = this.storageEntryTree;
for (const pathPart of pathComponents) {
if (!currentParent[pathPart]) {
@@ -172,7 +172,7 @@ export default class StorageModel {
}
};
printTree = (): string => {
readonly printTree = (): string => {
return stringify(this.storageEntryTree);
};
+11 -11
View File
@@ -36,15 +36,15 @@ export async function decryptString(
}
// process
export function encode(string: string): Uint8Array {
function encode(string: string): Uint8Array {
return new TextEncoder().encode(string);
}
export function decode(array: Uint8Array): string {
function decode(array: Uint8Array): string {
return new TextDecoder("utf-8").decode(array);
}
export async function encrypt(
async function encrypt(
iv: Uint8Array,
key: CryptoKey,
message: string,
@@ -57,7 +57,7 @@ export async function encrypt(
return new Uint8Array(arrayBuffer);
}
export async function decrypt(
async function decrypt(
iv: Uint8Array,
key: CryptoKey,
cyphertext: Uint8Array,
@@ -70,16 +70,16 @@ export async function decrypt(
return arrayBufferToString(arrayBuffer);
}
export async function hash(encoded: Uint8Array): Promise<ArrayBuffer> {
async function hash(encoded: Uint8Array): Promise<ArrayBuffer> {
return await crypto.subtle.digest("SHA-256", encoded);
}
// iv
export function generateIV(): Uint8Array {
function generateIV(): Uint8Array {
return crypto.getRandomValues(new Uint8Array(IV_SIZE));
}
export function splitMergedString(mergedString: string): [Uint8Array, string] {
function splitMergedString(mergedString: string): [Uint8Array, string] {
const iv = mergedString.slice(0, IV_SIZE);
const encryptedString = mergedString.slice(IV_SIZE);
@@ -87,7 +87,7 @@ export function splitMergedString(mergedString: string): [Uint8Array, string] {
}
// key
export async function importKey(
async function importKey(
passphrase: string,
purpose: "encrypt" | "decrypt",
): Promise<CryptoKey> {
@@ -101,15 +101,15 @@ export async function importKey(
}
// conversion
export function arrayBufferToString(arrayBuffer: ArrayBuffer): string {
function arrayBufferToString(arrayBuffer: ArrayBuffer): string {
const uInt8Array = new Uint8Array(arrayBuffer);
return decode(uInt8Array);
}
export function uInt8ToArray(uInt8Array: Uint8Array): number[] {
function uInt8ToArray(uInt8Array: Uint8Array): number[] {
return Array.from(uInt8Array);
}
export function arrayToUint8(array: number[]): Uint8Array {
function arrayToUint8(array: number[]): Uint8Array {
return new Uint8Array(array);
}
+9 -10
View File
@@ -1,5 +1,14 @@
// this file is responsible for migrating data from v1 to v2.
import { v4 } from "uuid";
import CoreViewModel from "../ViewModel/Global/coreViewModel";
import {
getLocalStorageItemAndClear,
parseArray,
parseOrFallback,
} from "../Model/Utility/utility";
import { checkMatchesObjectStructure } from "../Model/Utility/typeSafety";
import FileModel from "../Model/Files/fileModel";
import {
BoardInfoFileContent,
TaskFileContent,
@@ -8,16 +17,6 @@ import ChatModel, {
ChatMessage,
ChatMessageStatuses,
} from "../Model/Chat/chatModel";
import {
getLocalStorageItemAndClear,
parseArray,
parseOrFallback,
} from "../Model/Utility/utility";
import FileModel from "../Model/Files/fileModel";
import { checkMatchesObjectStructure } from "../Model/Utility/typeSafety";
import { v4 } from "uuid";
import CoreViewModel from "../ViewModel/Global/coreViewModel";
export default class v1Upgrader {
// general
+3 -5
View File
@@ -1,17 +1,15 @@
import * as React from "bloatless-react";
import { ViewController } from "../viewController";
import { TaskViewModelToEntry } from "../Components/taskEntry";
import {
PropertyValueList,
createPropertyValueIndexState,
} from "../Components/propertyValueList";
import BoardViewModel from "../../ViewModel/Pages/boardViewModel";
import { FilteredList } from "../Components/filteredList";
import { TaskCategoryBulkChangeViewModel } from "../../ViewModel/Utility/taskPropertyBulkChangeViewModel";
import TaskViewModel from "../../ViewModel/Pages/taskViewModel";
import { TaskViewModelToEntry } from "../Components/taskEntry";
import BoardViewModel from "../../ViewModel/Pages/boardViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { ViewController } from "../viewController";
export function BoardKanbanPage(
coreViewModel: CoreViewModel,
+8 -10
View File
@@ -1,18 +1,16 @@
import * as React from "bloatless-react";
import { BoardStatusGridPage } from "./boardStatusGridPage";
import { BoardKanbanPage } from "./boardKanbanPage";
import { ViewController } from "../viewController";
import { TaskSettingsModal } from "../Modals/taskSettingsModal";
import { SearchModal } from "../Modals/searchModal";
import { BoardSettingsModal } from "../Modals/boardSettingsModal";
import { TaskViewModelToEntry } from "../Components/taskEntry";
import { BoardViewToggleButton } from "../Components/boardViewToggleButton";
import BoardViewModel, {
BoardPageTypes,
} from "../../ViewModel/Pages/boardViewModel";
import { BoardKanbanPage } from "./boardKanbanPage";
import { BoardSettingsModal } from "../Modals/boardSettingsModal";
import { BoardStatusGridPage } from "./boardStatusGridPage";
import { BoardViewToggleButton } from "../Components/boardViewToggleButton";
import { SearchModal } from "../Modals/searchModal";
import { TaskSettingsModal } from "../Modals/taskSettingsModal";
import { TaskViewModelToEntry } from "../Components/taskEntry";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { ViewController } from "../viewController";
export function BoardPage(
coreViewModel: CoreViewModel,
+4 -6
View File
@@ -1,22 +1,20 @@
import * as React from "bloatless-react";
import { ViewController } from "../viewController";
import { TaskViewModelToEntry } from "../Components/taskEntry";
import {
PropertyValueList,
collectPropertyValuesToState,
createPropertyValueIndexState,
createSortedPropertyValueState,
} from "../Components/propertyValueList";
import { FilteredList } from "../Components/filteredList";
import {
TaskCategoryBulkChangeViewModel,
TaskStatusBulkChangeViewModel,
} from "../../ViewModel/Utility/taskPropertyBulkChangeViewModel";
import BoardViewModel from "../../ViewModel/Pages/boardViewModel";
import { FilteredList } from "../Components/filteredList";
import TaskViewModel from "../../ViewModel/Pages/taskViewModel";
import { TaskViewModelToEntry } from "../Components/taskEntry";
import BoardViewModel from "../../ViewModel/Pages/boardViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { ViewController } from "../viewController";
export function BoardStatusGridPage(
coreViewModel: CoreViewModel,
+5 -7
View File
@@ -1,14 +1,12 @@
import "./calendarPage.css";
import * as React from "bloatless-react";
import CalendarPageViewModel from "../../ViewModel/Pages/calendarPageViewModel";
import { MonthGrid } from "../Components/monthGrid";
import "./calendarPage.css";
import { ViewController } from "../viewController";
import { TaskSettingsModal } from "../Modals/taskSettingsModal";
import { TaskViewModelToEntry } from "../Components/taskEntry";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { PlaceholderView } from "../Components/placeholderView";
import { ViewController } from "../viewController";
import { MonthGrid } from "../Components/monthGrid";
import CalendarPageViewModel from "../../ViewModel/Pages/calendarPageViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
export function CalendarPage(
coreViewModel: CoreViewModel,
+5 -7
View File
@@ -1,14 +1,12 @@
import "./messagePage.css";
import * as React from "bloatless-react";
import "./messagePage.css";
import { ViewController } from "../viewController";
import { MessageFilterModal } from "../Modals/messageFilterModal";
import { ReplyPreview } from "../Components/replyPreview";
import { ChatMessage } from "../Components/chatMessage";
import MessagePageViewModel from "../../ViewModel/Pages/messagePageViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
import { ChatMessage } from "../Components/chatMessage";
import { MessageFilterModal } from "../Modals/messageFilterModal";
import { ViewController } from "../viewController";
import { ReplyPreview } from "../Components/replyPreview";
export function MessagePage(
coreViewModel: CoreViewModel,
+2 -4
View File
@@ -1,9 +1,7 @@
import * as React from "bloatless-react";
import { Colors } from "../../colors";
import { ColorPicker } from "../Components/colorPicker";
import { DangerousActionButton } from "../Components/dangerousActionButton";
import { DeletableListItem } from "../Components/deletableListItem";
import { DangerousActionButton } from "../Components/dangerousActionButton";
import { ColorPicker } from "../Components/colorPicker";
import SettingsPageViewModel from "../../ViewModel/Pages/settingsPageViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
+3 -6
View File
@@ -1,14 +1,11 @@
import "./taskPage.css";
import * as React from "bloatless-react";
import "./taskPage.css";
import { BoardPage } from "./boardPage";
import { ViewController } from "../viewController";
import { PlaceholderView } from "../Components/placeholderView";
import { BoardViewModelToEntry } from "../Components/boardEntry";
import TaskPageViewModel from "../../ViewModel/Pages/taskPageViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { PlaceholderView } from "../Components/placeholderView";
import { v4 } from "uuid";
import { ViewController } from "../viewController";
export function TaskPage(
coreViewModel: CoreViewModel,
+1 -2
View File
@@ -1,7 +1,6 @@
import * as React from "bloatless-react";
import BoardViewModel from "../../ViewModel/Pages/boardViewModel";
import { ViewController } from "../viewController";
import BoardViewModel from "../../ViewModel/Pages/boardViewModel";
export function BoardEntry(boardViewModel: BoardViewModel) {
const view = (
@@ -1,11 +1,9 @@
import * as React from "bloatless-react";
import { RibbonButton } from "./ribbonButton";
import BoardViewModel, {
BoardPageTypes,
} from "../../ViewModel/Pages/boardViewModel";
import { RibbonButton } from "./ribbonButton";
export function BoardViewToggleButton(
label: string,
icon: string,
-1
View File
@@ -1,5 +1,4 @@
import * as React from "bloatless-react";
import ChatViewModel from "../../ViewModel/Chat/chatViewModel";
export function ChatEntry(chatViewModel: ChatViewModel) {
+4 -6
View File
@@ -1,12 +1,10 @@
import * as React from "bloatless-react";
import { ChatMessageInfoModal } from "../Modals/chatMessageInfoModal";
import { ChatMessageStatuses } from "../../Model/Chat/chatModel";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
import { MessageReactionButtonRow } from "./messageReactionButtonRow";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { InlineReply } from "./inlineReply";
import { ViewController } from "../viewController";
import { ChatMessageInfoModal } from "../Modals/chatMessageInfoModal";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
import { ChatMessageStatuses } from "../../Model/Chat/chatModel";
export function ChatMessage(
coreViewModel: CoreViewModel,
+1 -3
View File
@@ -1,11 +1,9 @@
import * as React from "bloatless-react";
import { RibbonButton } from "./ribbonButton";
import ChatViewModel, {
ChatPageTypes,
} from "../../ViewModel/Chat/chatViewModel";
import { RibbonButton } from "./ribbonButton";
export function ChatViewToggleButton(
label: string,
icon: string,
-1
View File
@@ -1,5 +1,4 @@
import * as React from "bloatless-react";
import { Colors } from "../../colors";
export function ColorPicker(selectedColor: React.State<Colors>) {
+1 -3
View File
@@ -1,11 +1,9 @@
import * as React from "bloatless-react";
import StorageViewModel from "../../ViewModel/Global/storageViewModel";
import StorageModel, {
PATH_COMPONENT_SEPARATOR,
} from "../../Model/Global/storageModel";
import StorageViewModel from "../../ViewModel/Global/storageViewModel";
export function DirectoryItemList(
storageViewModel: StorageViewModel,
pathString: string = PATH_COMPONENT_SEPARATOR,
-1
View File
@@ -1,5 +1,4 @@
import * as React from "bloatless-react";
import {
StringEntryObject,
checkDoesObjectMatchReference,
+1 -3
View File
@@ -1,8 +1,6 @@
import * as React from "bloatless-react";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { ViewController } from "../viewController";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
export function InlineReply(chatMessageViewModel: ChatMessageViewModel) {
const reply = chatMessageViewModel.inlineReply;
@@ -1,10 +1,7 @@
import * as React from "bloatless-react";
import {
ChatMessageReaction,
ReactionSymbols,
} from "../../Model/Chat/chatModel";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
import { ReactionSymbols } from "../../Model/Chat/chatModel";
export function MessageReactionButton(
coreViewModel: CoreViewModel,
@@ -1,8 +1,8 @@
import * as React from "bloatless-react";
import { ReactionSymbols } from "../../Model/Chat/chatModel";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
import { MessageReactionButton } from "./messageReactionButton";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
import { ReactionSymbols } from "../../Model/Chat/chatModel";
export function MessageReactionButtonRow(
coreViewModel: CoreViewModel,
@@ -1,6 +1,4 @@
import * as React from "bloatless-react";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
import { ChatMessageReaction } from "../../Model/Chat/chatModel";
export function MessageReactionEntry(reaction: ChatMessageReaction) {
@@ -1,11 +1,6 @@
import * as React from "bloatless-react";
import {
ChatMessageReaction,
ReactionSymbols,
} from "../../Model/Chat/chatModel";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import MessagePageViewModel from "../../ViewModel/Pages/messagePageViewModel";
import { ReactionSymbols } from "../../Model/Chat/chatModel";
export function MessageReactionFilterButton(
messagePageViewModel: MessagePageViewModel,
+8 -7
View File
@@ -1,11 +1,10 @@
import "./monthGrid.css";
import * as React from "bloatless-react";
import { MonthGrid } from "../../Model/Files/calendarModel";
import TaskViewModel from "../../ViewModel/Pages/taskViewModel";
import { localeCompare } from "../../Model/Utility/utility";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import "./monthGrid.css";
import { ViewController } from "../viewController";
import TaskViewModel from "../../ViewModel/Pages/taskViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { localeCompare } from "../../Model/Utility/utility";
import { MonthGrid } from "../../Model/Files/calendarModel";
export function MonthGrid<T>(
coreViewModel: CoreViewModel,
@@ -69,7 +68,9 @@ export function MonthGrid<T>(
return (
monthGrid.isCurrentMonth == true &&
date ==
coreViewModel.unwrappedTodayDate.getDate().toString()
coreViewModel.unwrappedTodayDate
.getDate()
.toString()
);
},
);
@@ -1,5 +1,4 @@
import * as React from "bloatless-react";
import {
StringEntryObject,
collectObjectValuesForKey,
+1 -2
View File
@@ -1,7 +1,6 @@
import * as React from "bloatless-react";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
export function ReplyPreview(
coreViewModel: CoreViewModel,
-4
View File
@@ -1,9 +1,5 @@
import * as React from "bloatless-react";
import BoardViewModel, {
BoardPageTypes,
} from "../../ViewModel/Pages/boardViewModel";
export function RibbonButton(
label: string,
icon: string,
-1
View File
@@ -1,5 +1,4 @@
import * as React from "bloatless-react";
import TaskViewModel from "../../ViewModel/Pages/taskViewModel";
export function TaskEntry(taskViewModel: TaskViewModel) {
+4 -5
View File
@@ -1,10 +1,9 @@
import * as React from "bloatless-react";
import BoardViewModel from "../../ViewModel/Pages/boardViewModel";
import { ColorPicker } from "../Components/colorPicker";
import { DangerousActionButton } from "../Components/dangerousActionButton";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { ViewController } from "../viewController";
import { DangerousActionButton } from "../Components/dangerousActionButton";
import { ColorPicker } from "../Components/colorPicker";
import BoardViewModel from "../../ViewModel/Pages/boardViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
export function BoardSettingsModal(
coreViewModel: CoreViewModel,
+2 -3
View File
@@ -1,10 +1,9 @@
import * as React from "bloatless-react";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
import { MessageReactionEntry } from "../Components/messageReactionEntry";
import { MessageReactionButtonRow } from "../Components/messageReactionButtonRow";
import { InfoTile } from "../Components/infoTile";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { MessageReactionEntry } from "../Components/messageReactionEntry";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
export function ChatMessageInfoModal(
coreViewModel: CoreViewModel,
+1 -2
View File
@@ -1,8 +1,7 @@
import * as React from "bloatless-react";
import ConnectionViewModel from "../../ViewModel/Global/connectionViewModel";
import { DeletableListItem } from "../Components/deletableListItem";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import ConnectionViewModel from "../../ViewModel/Global/connectionViewModel";
export function ConnectionModal(
coreViewModel: CoreViewModel,
+3 -5
View File
@@ -1,15 +1,13 @@
import * as React from "bloatless-react";
import { ViewController } from "../viewController";
import { StringToTextSpan } from "../Components/textSpan";
import FileTransferViewModel, {
FileTransferModals,
FileTransferOption,
} from "../../ViewModel/Global/fileTransferViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import ConnectionViewModel from "../../ViewModel/Global/connectionViewModel";
import StorageModel from "../../Model/Global/storageModel";
import { StringToTextSpan } from "../Components/textSpan";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { ViewController } from "../viewController";
export function DataTransferModalWrapper(
coreViewModel: CoreViewModel,
+4 -5
View File
@@ -1,10 +1,9 @@
import * as React from "bloatless-react";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import MessagePageViewModel from "../../ViewModel/Pages/messagePageViewModel";
import { MessageReactionFilterButton } from "../Components/messageReactionFilterButton";
import { ReactionSymbols } from "../../Model/Chat/chatModel";
import { ViewController } from "../viewController";
import { MessageReactionFilterButton } from "../Components/messageReactionFilterButton";
import MessagePageViewModel from "../../ViewModel/Pages/messagePageViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { ReactionSymbols } from "../../Model/Chat/chatModel";
export function MessageFilterModal<T>(
coreViewModel: CoreViewModel,
+4 -5
View File
@@ -1,10 +1,9 @@
import * as React from "bloatless-react";
import SearchViewModel from "../../ViewModel/Utility/searchViewModel";
import { StringToOption } from "../Components/option";
import { v4 } from "uuid";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import * as React from "bloatless-react";
import { ViewController } from "../viewController";
import { StringToOption } from "../Components/option";
import SearchViewModel from "../../ViewModel/Utility/searchViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
export function SearchModal<T>(
coreViewModel: CoreViewModel,
+5 -8
View File
@@ -1,18 +1,15 @@
import * as React from "bloatless-react";
import { SplitModal } from "./splitModal";
import { languageNames } from "../translations";
import { PlaceholderView } from "../Components/placeholderView";
import { OptionButtonList } from "../Components/optionButtonList";
import { NavigationButton } from "../Components/navigationButton";
import { InfoTile } from "../Components/infoTile";
import SettingsViewModel, {
SettingsModalPages,
} from "../../ViewModel/Global/settingsViewModel";
import { SplitModal } from "./splitModal";
import { InfoTile } from "../Components/infoTile";
import { Option } from "../Components/option";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { Languages, ThemeSettings } from "../../Model/Global/settingsModel";
import { OptionButtonList } from "../Components/optionButtonList";
import { stringify } from "../../Model/Utility/utility";
import { PlaceholderView } from "../Components/placeholderView";
import { NavigationButton } from "../Components/navigationButton";
export function SettingsModal(
coreViewModel: CoreViewModel,
+2 -3
View File
@@ -1,7 +1,6 @@
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import "./splitModal.css";
import * as React from "bloatless-react";
import "./splitModal.css";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
export function SplitModal<T>(
coreViewModel: CoreViewModel,
+3 -5
View File
@@ -1,12 +1,10 @@
import * as React from "bloatless-react";
import { PATH_COMPONENT_SEPARATOR } from "../../Model/Global/storageModel";
import StorageViewModel from "../../ViewModel/Global/storageViewModel";
import { SplitModal } from "./splitModal";
import { DangerousActionButton } from "../Components/dangerousActionButton";
import { DirectoryItemList } from "../Components/directoryItemList";
import { DangerousActionButton } from "../Components/dangerousActionButton";
import StorageViewModel from "../../ViewModel/Global/storageViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { PATH_COMPONENT_SEPARATOR } from "../../Model/Global/storageModel";
export function StorageModal(
coreViewModel: CoreViewModel,
+1 -3
View File
@@ -1,15 +1,13 @@
import { v4 } from "uuid";
import * as React from "bloatless-react";
import {
Entry,
Option,
StringToOption,
VersionIdToOption,
} from "../Components/option";
import { DangerousActionButton } from "../Components/dangerousActionButton";
import TaskViewModel from "../../ViewModel/Pages/taskViewModel";
import { v4 } from "uuid";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
export function TaskSettingsModal(
+8 -11
View File
@@ -1,16 +1,13 @@
import "./homePage.css";
import * as React from "bloatless-react";
import ChatViewModel, { ChatPageTypes } from "../ViewModel/Chat/chatViewModel";
import { CalendarPage } from "./ChatPages/calendarPage";
import { ChatViewToggleButton } from "./Components/chatViewToggleButton";
import { MessagePage } from "./ChatPages/messagePage";
import { SettingsPage } from "./ChatPages/settingsPage";
import { TaskPage } from "./ChatPages/taskPage";
import CoreViewModel from "../ViewModel/Global/coreViewModel";
import { ViewController } from "./viewController";
import "./homePage.css";
import { ChatViewToggleButton } from "./Components/chatViewToggleButton";
import { TaskPage } from "./ChatPages/taskPage";
import { SettingsPage } from "./ChatPages/settingsPage";
import { MessagePage } from "./ChatPages/messagePage";
import { CalendarPage } from "./ChatPages/calendarPage";
import CoreViewModel from "../ViewModel/Global/coreViewModel";
import ChatViewModel, { ChatPageTypes } from "../ViewModel/Chat/chatViewModel";
export function ChatPage(
coreViewModel: CoreViewModel,
+2 -4
View File
@@ -1,10 +1,8 @@
import "./chatPage.css";
import * as React from "bloatless-react";
import ChatListViewModel from "../ViewModel/Chat/chatListViewModel";
import "./chatPage.css";
import { ChatPage } from "./chatPage";
import CoreViewModel from "../ViewModel/Global/coreViewModel";
import ChatListViewModel from "../ViewModel/Chat/chatListViewModel";
export function ChatPageWrapper(
coreViewModel: CoreViewModel,
+9 -12
View File
@@ -1,17 +1,14 @@
import "./homePage.css";
import * as React from "bloatless-react";
import { Option, StringToOption } from "./Components/option";
import ChatListViewModel from "../ViewModel/Chat/chatListViewModel";
import { ChatViewModelToChatEntry } from "./Components/chatEntry";
import ConnectionViewModel from "../ViewModel/Global/connectionViewModel";
import FileTransferViewModel from "../ViewModel/Global/fileTransferViewModel";
import SettingsViewModel from "../ViewModel/Global/settingsViewModel";
import StorageViewModel from "../ViewModel/Global/storageViewModel";
import CoreViewModel from "../ViewModel/Global/coreViewModel";
import "./homePage.css";
import { StringToOption } from "./Components/option";
import { HomePageButton } from "./Components/homePageButton";
import { ChatViewModelToChatEntry } from "./Components/chatEntry";
import StorageViewModel from "../ViewModel/Global/storageViewModel";
import SettingsViewModel from "../ViewModel/Global/settingsViewModel";
import FileTransferViewModel from "../ViewModel/Global/fileTransferViewModel";
import CoreViewModel from "../ViewModel/Global/coreViewModel";
import ConnectionViewModel from "../ViewModel/Global/connectionViewModel";
import ChatListViewModel from "../ViewModel/Chat/chatListViewModel";
export function HomePage(
coreViewModel: CoreViewModel,
+4 -5
View File
@@ -1,12 +1,11 @@
import * as React from "bloatless-react";
import ChatModel from "../../Model/Chat/chatModel";
import ChatViewModel from "./chatViewModel";
import CoreViewModel from "../Global/coreViewModel";
import { IndexManager } from "../../Model/Utility/utility";
import SettingsViewModel from "../Global/settingsViewModel";
import ConnectionViewModel from "../Global/connectionViewModel";
import NotificationViewModel from "../Global/notificationViewModel";
import CoreViewModel from "../Global/coreViewModel";
import ConnectionViewModel from "../Global/connectionViewModel";
import { IndexManager } from "../../Model/Utility/utility";
import ChatModel from "../../Model/Chat/chatModel";
export default class ChatListViewModel {
notificationViewModel: NotificationViewModel;
+2 -4
View File
@@ -1,5 +1,6 @@
import * as React from "bloatless-react";
import MessagePageViewModel from "../Pages/messagePageViewModel";
import CoreViewModel from "../Global/coreViewModel";
import {
ChatMessage,
ChatMessageReaction,
@@ -7,9 +8,6 @@ import {
ReactionSymbols,
} from "../../Model/Chat/chatModel";
import CoreViewModel from "../Global/coreViewModel";
import MessagePageViewModel from "../Pages/messagePageViewModel";
export default class ChatMessageViewModel {
// data
chatMessage: ChatMessage;
+15 -18
View File
@@ -1,29 +1,26 @@
import * as React from "bloatless-react";
import ChatListViewModel from "./chatListViewModel";
import TaskPageViewModel from "../Pages/taskPageViewModel";
import SettingsPageViewModel from "../Pages/settingsPageViewModel";
import MessagePageViewModel from "../Pages/messagePageViewModel";
import CalendarPageViewModel, {
CALENDAR_EVENT_BOARD_ID,
} from "../Pages/calendarPageViewModel";
import ChatModel, {
ChatMessage,
ChatMessageReaction,
} from "../../Model/Chat/chatModel";
import SettingsViewModel from "../Global/settingsViewModel";
import NotificationViewModel from "../Global/notificationViewModel";
import CoreViewModel, { Context, ContextHost } from "../Global/coreViewModel";
import ConnectionViewModel from "../Global/connectionViewModel";
import { Colors } from "../../colors";
import { CommonKeys } from "../../View/keystrokes";
import { Entry } from "../../View/Components/option";
import StorageModel, {
StorageModelSubPaths,
filePaths,
} from "../../Model/Global/storageModel";
import ChatListViewModel from "./chatListViewModel";
import { Colors } from "../../colors";
import CoreViewModel, { Context, ContextHost } from "../Global/coreViewModel";
import { Entry } from "../../View/Components/option";
import MessagePageViewModel from "../Pages/messagePageViewModel";
import SettingsPageViewModel from "../Pages/settingsPageViewModel";
import SettingsViewModel from "../Global/settingsViewModel";
import TaskPageViewModel from "../Pages/taskPageViewModel";
import ConnectionViewModel from "../Global/connectionViewModel";
import NotificationViewModel from "../Global/notificationViewModel";
import { v4 } from "uuid";
import { CommonKeys } from "../../View/keystrokes";
import ChatModel, {
ChatMessage,
ChatMessageReaction,
} from "../../Model/Chat/chatModel";
export default class ChatViewModel extends ContextHost<ChatPageTypes> {
calendarViewModel: CalendarPageViewModel;
@@ -1,6 +1,4 @@
import * as React from "bloatless-react";
import ConnectionModel from "../../Model/Global/connectionModel";
import CoreViewModel from "./coreViewModel";
export default class ConnectionViewModel {
+6 -5
View File
@@ -1,12 +1,12 @@
import { v4 } from "uuid";
import * as React from "bloatless-react";
import SettingsModel from "../../Model/Global/settingsModel";
import { allTranslations, Translations } from "../../View/translations";
import { HandlerManager } from "../../Model/Utility/utility";
import StorageModel from "../../Model/Global/storageModel";
import SettingsModel from "../../Model/Global/settingsModel";
import FileTransferModel from "../../Model/Global/fileTransferModel";
import ConnectionModel from "../../Model/Global/connectionModel";
import ChatListModel from "../../Model/Chat/chatListModel";
import FileTransferModel from "../../Model/Global/fileTransferModel";
import { v4 } from "uuid";
import { HandlerManager } from "../../Model/Utility/utility";
export default class CoreViewModel {
readonly BUILD = "Build 26.04.16.A";
@@ -72,7 +72,8 @@ export default class CoreViewModel {
handleChron = (): void => {
const newDate = new Date();
if (this.unwrappedTodayDate.toDateString() == newDate.toDateString()) return;
if (this.unwrappedTodayDate.toDateString() == newDate.toDateString())
return;
this.todayDate.value = new Date();
};
@@ -1,16 +1,12 @@
import * as React from "bloatless-react";
import FileTransferModel, {
TransferData,
} from "../../Model/Global/fileTransferModel";
import CoreViewModel, { Context } from "./coreViewModel";
import { CommonKeys } from "../../View/keystrokes";
import StorageModel, {
StorageModelSubPaths,
filePaths,
} from "../../Model/Global/storageModel";
import { TransferData } from "../../Model/Global/fileTransferModel";
import ChatModel from "../../Model/Chat/chatModel";
import CoreViewModel, { Context } from "./coreViewModel";
import { CommonKeys } from "../../View/keystrokes";
export default class FileTransferViewModel extends Context {
// state
@@ -1,7 +1,7 @@
import * as React from "bloatless-react";
import ChatModel, { ChatMessage } from "../../Model/Chat/chatModel";
import ChatListViewModel from "../Chat/chatListViewModel";
import { ChatPageTypes } from "../Chat/chatViewModel";
import ChatListViewModel from "../Chat/chatListViewModel";
import ChatModel, { ChatMessage } from "../../Model/Chat/chatModel";
export default class NotificationViewModel {
// data
+1 -2
View File
@@ -1,8 +1,7 @@
import * as React from "bloatless-react";
import CoreViewModel, { Context } from "./coreViewModel";
import { Languages, ThemeSettings } from "../../Model/Global/settingsModel";
import { CommonKeys } from "../../View/keystrokes";
import { Languages, ThemeSettings } from "../../Model/Global/settingsModel";
export default class SettingsViewModel extends Context {
// state
+2 -4
View File
@@ -1,12 +1,10 @@
import * as React from "bloatless-react";
import CoreViewModel, { Context } from "./coreViewModel";
import { CommonKeys } from "../../View/keystrokes";
import StorageModel, {
PATH_COMPONENT_SEPARATOR,
} from "../../Model/Global/storageModel";
import CoreViewModel, { Context } from "./coreViewModel";
import { CommonKeys } from "../../View/keystrokes";
export default class StorageViewModel extends Context {
// state
isShowingStorageModal: React.State<boolean> = new React.State(false);
+8 -10
View File
@@ -1,19 +1,17 @@
import * as React from "bloatless-react";
import TaskViewModel from "./taskViewModel";
import TaskPageViewModel from "./taskPageViewModel";
import TaskContainingPageViewModel from "./taskContainingPageViewModel";
import SearchViewModel from "../Utility/searchViewModel";
import CoreViewModel from "../Global/coreViewModel";
import ChatViewModel, { ChatPageTypes } from "../Chat/chatViewModel";
import { Colors } from "../../colors";
import { CommonKeys } from "../../View/keystrokes";
import BoardsAndTasksModel, {
BoardInfoFileContent,
TaskFileContent,
} from "../../Model/Files/boardsAndTasksModel";
import ChatViewModel, { ChatPageTypes } from "../Chat/chatViewModel";
import { Colors } from "../../colors";
import CoreViewModel from "../Global/coreViewModel";
import SearchViewModel from "../Utility/searchViewModel";
import TaskContainingPageViewModel from "./taskContainingPageViewModel";
import TaskPageViewModel from "./taskPageViewModel";
import TaskViewModel from "./taskViewModel";
import { CommonKeys } from "../../View/keystrokes";
export default class BoardViewModel extends TaskContainingPageViewModel {
// state
name: React.State<string> = new React.State("");
+6 -8
View File
@@ -1,15 +1,13 @@
import * as React from "bloatless-react";
import TaskViewModel from "./taskViewModel";
import TaskContainingPageViewModel from "./taskContainingPageViewModel";
import CoreViewModel from "../Global/coreViewModel";
import ChatViewModel, { ChatPageTypes } from "../Chat/chatViewModel";
import { CommonKeys } from "../../View/keystrokes";
import CalendarModel, { MonthGrid } from "../../Model/Files/calendarModel";
import BoardsAndTasksModel, {
TaskFileContent,
} from "../../Model/Files/boardsAndTasksModel";
import CalendarModel, { MonthGrid } from "../../Model/Files/calendarModel";
import ChatViewModel, { ChatPageTypes } from "../Chat/chatViewModel";
import CoreViewModel from "../Global/coreViewModel";
import TaskContainingPageViewModel from "./taskContainingPageViewModel";
import TaskViewModel from "./taskViewModel";
import { CommonKeys } from "../../View/keystrokes";
export const CALENDAR_EVENT_BOARD_ID = "events";
+5 -5
View File
@@ -1,9 +1,9 @@
import { CommonKeys } from "../../View/keystrokes";
import ConnectionViewModel from "../Global/connectionViewModel";
import CoreViewModel, { Context } from "../Global/coreViewModel";
import FileTransferViewModel from "../Global/fileTransferViewModel";
import SettingsViewModel from "../Global/settingsViewModel";
import StorageViewModel from "../Global/storageViewModel";
import SettingsViewModel from "../Global/settingsViewModel";
import FileTransferViewModel from "../Global/fileTransferViewModel";
import CoreViewModel, { Context } from "../Global/coreViewModel";
import ConnectionViewModel from "../Global/connectionViewModel";
import { CommonKeys } from "../../View/keystrokes";
export default class HomeViewModel extends Context {
constructor(
+5 -7
View File
@@ -1,16 +1,14 @@
import * as React from "bloatless-react";
import SearchViewModel from "../Utility/searchViewModel";
import CoreViewModel, { Context } from "../Global/coreViewModel";
import ChatViewModel, { ChatPageTypes } from "../Chat/chatViewModel";
import ChatMessageViewModel from "../Chat/chatMessageViewModel";
import { CommonKeys } from "../../View/keystrokes";
import {
ChatMessage,
ChatMessageReaction,
ReactionSymbols,
} from "../../Model/Chat/chatModel";
import ChatMessageViewModel from "../Chat/chatMessageViewModel";
import ChatViewModel, { ChatPageTypes } from "../Chat/chatViewModel";
import CoreViewModel, { Context } from "../Global/coreViewModel";
import SearchViewModel from "../Utility/searchViewModel";
import { v4 } from "uuid";
import { CommonKeys } from "../../View/keystrokes";
export default class MessagePageViewModel extends Context {
// state
+1 -2
View File
@@ -1,8 +1,7 @@
import * as React from "bloatless-react";
import CoreViewModel, { Context } from "../Global/coreViewModel";
import ChatViewModel, { ChatPageTypes } from "../Chat/chatViewModel";
import { Colors } from "../../colors";
import CoreViewModel, { Context } from "../Global/coreViewModel";
export default class SettingsPageViewModel extends Context {
// state
@@ -1,14 +1,12 @@
import * as React from "bloatless-react";
import TaskViewModel from "./taskViewModel";
import CoreViewModel, { Context } from "../Global/coreViewModel";
import ChatViewModel from "../Chat/chatViewModel";
import { IndexManager } from "../../Model/Utility/utility";
import BoardsAndTasksModel, {
TaskFileContent,
} from "../../Model/Files/boardsAndTasksModel";
import ChatViewModel from "../Chat/chatViewModel";
import CoreViewModel, { Context } from "../Global/coreViewModel";
import { IndexManager } from "../../Model/Utility/utility";
import TaskViewModel from "./taskViewModel";
export default class TaskContainingPageViewModel extends Context {
// state
readonly taskIndexManager = new IndexManager<TaskViewModel>(
+5 -7
View File
@@ -1,15 +1,13 @@
import * as React from "bloatless-react";
import BoardViewModel from "./boardViewModel";
import CoreViewModel, { ContextHost } from "../Global/coreViewModel";
import ChatViewModel, { ChatPageTypes } from "../Chat/chatViewModel";
import { CommonKeys } from "../../View/keystrokes";
import { IndexManager } from "../../Model/Utility/utility";
import BoardsAndTasksModel, {
BoardInfoFileContent,
} from "../../Model/Files/boardsAndTasksModel";
import BoardViewModel, { BoardPageTypes } from "./boardViewModel";
import ChatViewModel, { ChatPageTypes } from "../Chat/chatViewModel";
import CoreViewModel, { Context, ContextHost } from "../Global/coreViewModel";
import { IndexManager } from "../../Model/Utility/utility";
import { CommonKeys } from "../../View/keystrokes";
export default class TaskPageViewModel extends ContextHost<string> {
// data
readonly boardIndexManager = new IndexManager<BoardViewModel>(
+6 -8
View File
@@ -1,15 +1,13 @@
import * as React from "bloatless-react";
import TaskContainingPageViewModel from "./taskContainingPageViewModel";
import CoreViewModel, { Context } from "../Global/coreViewModel";
import ChatViewModel from "../Chat/chatViewModel";
import { ViewController } from "../../View/viewController";
import { CommonKeys } from "../../View/keystrokes";
import { localeCompare, padZero } from "../../Model/Utility/utility";
import BoardsAndTasksModel, {
TaskFileContent,
} from "../../Model/Files/boardsAndTasksModel";
import { localeCompare, padZero } from "../../Model/Utility/utility";
import ChatViewModel from "../Chat/chatViewModel";
import CoreViewModel, { Context } from "../Global/coreViewModel";
import TaskContainingPageViewModel from "./taskContainingPageViewModel";
import { CommonKeys } from "../../View/keystrokes";
import { ViewController } from "../../View/viewController";
export default class TaskViewModel extends Context {
// util
-1
View File
@@ -1,5 +1,4 @@
import * as React from "bloatless-react";
import { checkDoesObjectMatchSearch } from "../../Model/Utility/utility";
export default class SearchViewModel<T> {
@@ -1,5 +1,4 @@
import * as React from "bloatless-react";
import TaskViewModel from "../Pages/taskViewModel";
export default class TaskPropertyBulkChangeViewModel {
+20 -22
View File
@@ -1,28 +1,26 @@
import "./base.css";
import * as React from "bloatless-react";
import "./colors.css";
import "./coloredTile.css";
import * as React from "bloatless-react";
import ChatListModel from "./Model/Chat/chatListModel";
import ChatListViewModel from "./ViewModel/Chat/chatListViewModel";
import { ChatPageWrapper } from "./View/chatPageWrapper";
import { ConnectionModal } from "./View/Modals/connectionModal";
import ConnectionModel from "./Model/Global/connectionModel";
import ConnectionViewModel from "./ViewModel/Global/connectionViewModel";
import CoreViewModel from "./ViewModel/Global/coreViewModel";
import { DataTransferModalWrapper } from "./View/Modals/dataTransferModal";
import FileTransferModel from "./Model/Global/fileTransferModel";
import FileTransferViewModel from "./ViewModel/Global/fileTransferViewModel";
import { HomePage } from "./View/homePage";
import SettingsModel from "./Model/Global/settingsModel";
import SettingsViewModel from "./ViewModel/Global/settingsViewModel";
import { StorageModal } from "./View/Modals/storageModal";
import StorageModel from "./Model/Global/storageModel";
import StorageViewModel from "./ViewModel/Global/storageViewModel";
import v1Upgrader from "./Upgrader/v1";
import { SettingsModal } from "./View/Modals/settingsModal";
import "./base.css";
import HomeViewModel from "./ViewModel/Pages/homeViewModel";
import StorageViewModel from "./ViewModel/Global/storageViewModel";
import SettingsViewModel from "./ViewModel/Global/settingsViewModel";
import FileTransferViewModel from "./ViewModel/Global/fileTransferViewModel";
import CoreViewModel from "./ViewModel/Global/coreViewModel";
import ConnectionViewModel from "./ViewModel/Global/connectionViewModel";
import ChatListViewModel from "./ViewModel/Chat/chatListViewModel";
import { HomePage } from "./View/homePage";
import { ChatPageWrapper } from "./View/chatPageWrapper";
import { StorageModal } from "./View/Modals/storageModal";
import { SettingsModal } from "./View/Modals/settingsModal";
import { DataTransferModalWrapper } from "./View/Modals/dataTransferModal";
import { ConnectionModal } from "./View/Modals/connectionModal";
import v1Upgrader from "./Upgrader/v1";
import StorageModel from "./Model/Global/storageModel";
import SettingsModel from "./Model/Global/settingsModel";
import FileTransferModel from "./Model/Global/fileTransferModel";
import ConnectionModel from "./Model/Global/connectionModel";
import ChatListModel from "./Model/Chat/chatListModel";
// models
const storageModel = new StorageModel();