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