diff --git a/dist/index.css b/dist/index.css
index b2c172cb..9b0eebc0 100644
--- a/dist/index.css
+++ b/dist/index.css
@@ -475,6 +475,7 @@ body[showing-chat] #chat-page-wrapper {
width: 100%;
max-width: 100%;
padding: 0px;
+ overflow: hidden;
}
#chat-page > div > #main > #task-page > .pane-wrapper > .pane > .main-content > div {
animation: slide-up var(--animation-duration);
@@ -485,14 +486,12 @@ body[showing-chat] #chat-page-wrapper {
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 {
+#chat-page > div > #main > #task-page .zoom {
display: flex;
align-items: start;
gap: var(--large-gap);
- width: 100%;
- height: 100%;
- overflow: visible;
+ width: auto;
+ height: auto;
transform-origin: top left;
padding: var(--content-padding);
}
diff --git a/dist/index.js b/dist/index.js
index e507e5c5..de2e9241 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -1136,32 +1136,82 @@
function localeCompare(a, b) {
return a.localeCompare(b);
}
- function implementPinchZoom(element) {
- let initialDistance = 0;
+ function implementPinchZoom(targetSelector) {
let pinching = false;
+ let initialDistance = 0;
+ let currentZoom = 1;
+ let initialZoom = 1;
+ let currentX = 0;
+ let currentY = 0;
+ let initialX = 0;
+ let initialY = 0;
+ let initialTouchX = 0;
+ let initialTouchY = 0;
+ const MIN = 0.25;
+ const MAX = 5;
+ const element = () => canvas.querySelector(targetSelector);
+ const parent = () => element().parentElement;
const distance = (e) => Math.hypot(
e.touches[0].pageX - e.touches[1].pageX,
e.touches[0].pageY - e.touches[1].pageY
);
- function apply(factor) {
- element.style.transform = `scale(${(Math.floor(factor * 100) / 100).toString()})`;
+ const point = (e, direction, i) => e.touches[i][direction == "x" ? "clientX" : "clientY"];
+ const midpoint = (e, direction) => (point(e, direction, 0) + point(e, direction, 1)) / 2;
+ function apply(factor, offset) {
+ if (factor < MIN) return apply(MIN, offset);
+ if (factor > MAX) return apply(5, offset);
+ if (!element) return;
+ const [x, y] = offset;
+ element().style.transform = `scale(${(Math.floor(factor * 100) / 100).toString()}) translate(${x}px, ${y}px)`;
+ currentX = x;
+ currentY = y;
+ currentZoom = factor;
}
- element.addEventListener("touchstart", (event) => {
- if (event.touches.length != 2) return;
- initialDistance = distance(event);
+ const canvas = document.body;
+ canvas.addEventListener("touchstart", (event) => {
+ document.activeElement.blur();
+ initialZoom = currentZoom;
+ initialX = currentX;
+ initialY = currentY;
+ if (event.touches.length != 2) {
+ pinching = false;
+ initialTouchX = event.touches[0].clientX;
+ initialTouchY = event.touches[0].clientY;
+ return;
+ }
pinching = true;
- apply(1);
+ initialDistance = distance(event);
+ initialTouchX = midpoint(event, "x");
+ initialTouchY = midpoint(event, "y");
});
- element.addEventListener("touchend", (event) => {
- if (event.touches.length == 2) return;
- pinching = false;
- });
- element.addEventListener("touchmove", (event) => {
- if (!pinching) return;
+ canvas.addEventListener("touchmove", (event) => {
+ if (!pinching) {
+ apply(currentZoom, [
+ initialX + (event.touches[0].clientX - initialTouchX) / initialZoom,
+ initialY + (event.touches[0].clientY - initialTouchY) / initialZoom
+ ]);
+ return;
+ }
+ if (event.touches.length < 2) return;
event.preventDefault();
const currentDistance = distance(event);
- const factor = currentDistance / initialDistance;
- apply(factor);
+ const midX = midpoint(event, "x");
+ const midY = midpoint(event, "y");
+ const ratio = currentDistance / initialDistance;
+ const difference = currentDistance - initialDistance;
+ apply(initialZoom * ratio, [initialX + (midX - difference - initialTouchX) / initialZoom, initialY + (midY - difference - initialTouchY) / initialZoom]);
+ });
+ canvas.addEventListener("wheel", (event) => {
+ event.preventDefault();
+ if (!event.shiftKey) {
+ apply(currentZoom, [currentX - event.deltaX, currentY - event.deltaY]);
+ return;
+ }
+ ;
+ apply(currentZoom + (event.deltaY < 0 ? 1 : -1) * 0.1, [initialX, initialY]);
+ });
+ canvas.addEventListener("scroll", (event) => {
+ event.preventDefault();
});
}
@@ -1174,7 +1224,7 @@
this.connectionModel = connectionModel2;
this.chatListModel = chatListModel2;
this.fileTransferModel = fileTransferModel2;
- this.BUILD = "Build 26.08.30.C";
+ this.BUILD = "Build 26.08.30.D";
// CONTEXT
this.contextStack = /* @__PURE__ */ new Map();
this.closeContext = (contextId, fromHistoryEvent = false) => {
@@ -1858,7 +1908,10 @@
};
this.downloadFile = async () => {
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
- const backup = await this.coreViewModel.fileTransferModel.generateBackup(this.selectedPaths.value.values(), this.exportKey.value);
+ const backup = await this.coreViewModel.fileTransferModel.generateBackup(
+ this.selectedPaths.value.values(),
+ this.exportKey.value
+ );
const anchor = document.createElement("a");
anchor.href = window.URL.createObjectURL(backup);
anchor.download = `comms-${date}.bak`;
@@ -1888,7 +1941,10 @@
if (!fileString || !key) return;
this.cannotDecryptImport.value = true;
try {
- await this.coreViewModel.fileTransferModel.handleBackupFile(fileString, key);
+ await this.coreViewModel.fileTransferModel.handleBackupFile(
+ fileString,
+ key
+ );
window.location.reload();
} catch (e) {
console.error(e);
@@ -4907,7 +4963,7 @@
const index = createPropertyValueIndexState(sortedStatuses, statusName);
return StatusNameCell(coreViewModel2, statusName, index, boardViewModel);
};
- const main = /* @__PURE__ */ createElement("div", { class: "status-page-content" }, /* @__PURE__ */ createElement(
+ return /* @__PURE__ */ createElement("div", { class: "status-page-content zoom" }, /* @__PURE__ */ createElement(
"div",
{
class: "status-name-row",
@@ -4941,8 +4997,6 @@
);
}
));
- implementPinchZoom(main);
- return main;
}
function StatusNameCell(coreViewModel2, statusName, index, boardViewModel) {
const taskViewModelsWithMatchingStatus = new ListState();
@@ -5066,7 +5120,7 @@
// src/View/ChatPages/boardKanbanPage.tsx
function BoardKanbanPage(coreViewModel2, boardViewModel) {
- const main = PropertyValueList(
+ return PropertyValueList(
"category",
(taskViewModel) => taskViewModel.task,
boardViewModel.filteredTaskViewModels,
@@ -5086,14 +5140,12 @@
return /* @__PURE__ */ createElement(
"div",
{
- class: "kanban-board-wrapper",
+ class: "kanban-board-wrapper zoom",
"children:append": [categories, categoryNameConverter]
}
);
}
);
- implementPinchZoom(main);
- return main;
}
function Column(coreViewModel2, categoryName, index, boardViewModel) {
return FilteredList(
@@ -6800,9 +6852,7 @@
function toggle() {
isSelected.value = !isSelected.value;
}
- return /* @__PURE__ */ createElement("button", { class: "tile", "toggle:selected": isSelected, "on:click": toggle }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("b", { class: "ellipsis" }, fileOption.label), /* @__PURE__ */ createElement("span", { class: "secondary ellipsis" }, StorageModel.pathComponentsToString(
- ...fileOption.path
- ))));
+ return /* @__PURE__ */ createElement("button", { class: "tile", "toggle:selected": isSelected, "on:click": toggle }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("b", { class: "ellipsis" }, fileOption.label), /* @__PURE__ */ createElement("span", { class: "secondary ellipsis" }, StorageModel.pathComponentsToString(...fileOption.path))));
}
function DirectionSelectionModal(coreViewModel2, connectionViewModel2, fileTransferViewModel2) {
const isPresented = createProxyState(
@@ -6813,55 +6863,45 @@
[connectionViewModel2.isConnected],
() => connectionViewModel2.isConnected.value == false
);
- return /* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": isPresented }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, coreViewModel2.translations.dataTransferModal.transferDataHeadline), /* @__PURE__ */ createElement(
- "div",
+ return /* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": isPresented }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, coreViewModel2.translations.dataTransferModal.transferDataHeadline), /* @__PURE__ */ createElement("div", { class: "flex-column gap content-margin-bottom" }, /* @__PURE__ */ createElement(
+ "button",
{
- class: "flex-column gap content-margin-bottom"
+ class: "tile",
+ "toggle:disabled": isDisconnected,
+ "on:click": fileTransferViewModel2.showFileSelectionModal
},
- /* @__PURE__ */ createElement(
- "button",
- {
- class: "tile",
- "toggle:disabled": isDisconnected,
- "on:click": fileTransferViewModel2.showFileSelectionModal
- },
- /* @__PURE__ */ createElement("span", { class: "icon" }, "share_windows"),
- /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("b", null, coreViewModel2.translations.dataTransferModal.fromThisDeviceButton)),
- /* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
- ),
- /* @__PURE__ */ createElement(
- "button",
- {
- class: "tile",
- "toggle:disabled": isDisconnected,
- "on:click": fileTransferViewModel2.showTransferDataInputModal
- },
- /* @__PURE__ */ createElement("span", { class: "icon" }, "cloud_download"),
- /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("b", null, coreViewModel2.translations.dataTransferModal.toThisDeviceButton)),
- /* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
- ),
- /* @__PURE__ */ createElement("hr", null),
- /* @__PURE__ */ createElement(
- "button",
- {
- class: "tile",
- "on:click": fileTransferViewModel2.showExportSelectionModal
- },
- /* @__PURE__ */ createElement("span", { class: "icon" }, "file_save"),
- /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("b", null, coreViewModel2.translations.dataTransferModal.exportButton)),
- /* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
- ),
- /* @__PURE__ */ createElement(
- "button",
- {
- class: "tile",
- "on:click": fileTransferViewModel2.showImportModal
- },
- /* @__PURE__ */ createElement("span", { class: "icon" }, "upload_file"),
- /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("b", null, coreViewModel2.translations.dataTransferModal.importButton)),
- /* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
- )
- )), /* @__PURE__ */ createElement("button", { "on:click": fileTransferViewModel2.close }, coreViewModel2.translations.general.closeButton, /* @__PURE__ */ createElement("span", { class: "icon" }, "close"))));
+ /* @__PURE__ */ createElement("span", { class: "icon" }, "share_windows"),
+ /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("b", null, coreViewModel2.translations.dataTransferModal.fromThisDeviceButton)),
+ /* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
+ ), /* @__PURE__ */ createElement(
+ "button",
+ {
+ class: "tile",
+ "toggle:disabled": isDisconnected,
+ "on:click": fileTransferViewModel2.showTransferDataInputModal
+ },
+ /* @__PURE__ */ createElement("span", { class: "icon" }, "cloud_download"),
+ /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("b", null, coreViewModel2.translations.dataTransferModal.toThisDeviceButton)),
+ /* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
+ ), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement(
+ "button",
+ {
+ class: "tile",
+ "on:click": fileTransferViewModel2.showExportSelectionModal
+ },
+ /* @__PURE__ */ createElement("span", { class: "icon" }, "file_save"),
+ /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("b", null, coreViewModel2.translations.dataTransferModal.exportButton)),
+ /* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
+ ), /* @__PURE__ */ createElement(
+ "button",
+ {
+ class: "tile",
+ "on:click": fileTransferViewModel2.showImportModal
+ },
+ /* @__PURE__ */ createElement("span", { class: "icon" }, "upload_file"),
+ /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("b", null, coreViewModel2.translations.dataTransferModal.importButton)),
+ /* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
+ ))), /* @__PURE__ */ createElement("button", { "on:click": fileTransferViewModel2.close }, coreViewModel2.translations.general.closeButton, /* @__PURE__ */ createElement("span", { class: "icon" }, "close"))));
}
function FileSelectionModal(coreViewModel2, fileTransferViewModel2) {
const OptionConverter = (fileOption) => {
@@ -7118,7 +7158,14 @@
[fileTransferViewModel2.presentedModal],
() => fileTransferViewModel2.presentedModal.value == 8 /* ImportSelection */
);
- return /* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": isPresented }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, coreViewModel2.translations.dataTransferModal.importHeadline), /* @__PURE__ */ createElement("div", { class: "flex-column gap content-margin-bottom" }, /* @__PURE__ */ createElement("input", { id: "file-transfer-input", type: "file", "on:change": fileTransferViewModel2.updateImportSelection }))), /* @__PURE__ */ createElement("div", { class: "flex-row width-100" }, /* @__PURE__ */ createElement(
+ return /* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": isPresented }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, coreViewModel2.translations.dataTransferModal.importHeadline), /* @__PURE__ */ createElement("div", { class: "flex-column gap content-margin-bottom" }, /* @__PURE__ */ createElement(
+ "input",
+ {
+ id: "file-transfer-input",
+ type: "file",
+ "on:change": fileTransferViewModel2.updateImportSelection
+ }
+ ))), /* @__PURE__ */ createElement("div", { class: "flex-row width-100" }, /* @__PURE__ */ createElement(
"button",
{
class: "flex",
@@ -8031,4 +8078,5 @@
StorageModal(coreViewModel, storageViewModel),
SettingsModal(coreViewModel, settingsViewModel)
);
+ implementPinchZoom(".zoom");
})();
diff --git a/src/Model/Global/fileTransferModel.ts b/src/Model/Global/fileTransferModel.ts
index 1a24b637..f3143caa 100644
--- a/src/Model/Global/fileTransferModel.ts
+++ b/src/Model/Global/fileTransferModel.ts
@@ -149,14 +149,15 @@ export default class FileTransferModel {
});
}
const rawBackup = stringify(files);
- console.log(rawBackup);
+ console.log(rawBackup);
const encrypted = await encryptString(rawBackup, passphrase);
- const blob = new Blob([encrypted], {type: "text/plain"});
- return blob;
+ const blob = new Blob([encrypted], { type: "text/plain" });
+ return blob;
};
readonly prepareFileForSending = (filePath: string[]): string => {
- const fileContent: string | undefined = this.storageModel.read(filePath);
+ const fileContent: string | undefined =
+ this.storageModel.read(filePath);
if (fileContent == null) return "";
const fileData: FileData = {
diff --git a/src/Model/Utility/utility.ts b/src/Model/Utility/utility.ts
index 8640a8c1..65e61c35 100644
--- a/src/Model/Utility/utility.ts
+++ b/src/Model/Utility/utility.ts
@@ -278,32 +278,95 @@ export function localeCompare(a: string, b: string): number {
return a.localeCompare(b);
}
-// ui
-export function implementPinchZoom(element: HTMLElement) {
- let initialDistance = 0;
+// ui
+export function implementPinchZoom(targetSelector: string) {
let pinching = false;
- const distance = (e: TouchEvent) => Math.hypot(e.touches[0].pageX - e.touches[1].pageX,
- e.touches[0].pageY - e.touches[1].pageY);
- function apply(factor) {
- element.style.transform = `scale(${(Math.floor(factor*100)/100).toString()})`;
+ let initialDistance = 0;
+
+ let currentZoom = 1;
+ let initialZoom = 1;
+
+ let currentX = 0;
+ let currentY = 0;
+ let initialX = 0;
+ let initialY = 0;
+ let initialTouchX = 0;
+ let initialTouchY = 0;
+
+ const MIN = 0.25;
+ const MAX = 5;
+
+ const element = (): HTMLElement => canvas.querySelector(targetSelector);
+ const parent = (): HTMLElement => element().parentElement;
+ const distance = (e: TouchEvent) =>
+ Math.hypot(
+ e.touches[0].pageX - e.touches[1].pageX,
+ e.touches[0].pageY - e.touches[1].pageY,
+ );
+ const point = (e: TouchEvent, direction: "x" | "y", i: number) =>
+ e.touches[i][direction == "x" ? "clientX" : "clientY"];
+ const midpoint = (e: TouchEvent, direction: "x" | "y") =>
+ (point(e, direction, 0) + point(e, direction, 1)) / 2;
+
+ function apply(factor: number, offset: [number, number]) {
+ if (factor < MIN) return apply(MIN, offset);
+ if (factor > MAX) return apply(5, offset);
+ if (!element) return;
+
+ const [x, y] = offset;
+ element().style.transform = `scale(${(Math.floor(factor * 100) / 100).toString()}) translate(${x}px, ${y}px)`;
+ currentX = x;
+ currentY = y;
+ currentZoom = factor;
}
- element.addEventListener("touchstart", (event: TouchEvent) => {
- if (event.touches.length != 2) return;
- initialDistance = distance(event);
+ const canvas = document.body;
+ canvas.addEventListener("touchstart", (event: TouchEvent) => {
+ (document.activeElement as HTMLElement).blur();
+
+ initialZoom = currentZoom;
+ initialX = currentX;
+ initialY = currentY;
+
+ if (event.touches.length != 2) {
+ pinching = false;
+ initialTouchX = event.touches[0].clientX;
+ initialTouchY = event.touches[0].clientY;
+ return;
+ }
+
pinching = true;
- apply(1);
+ initialDistance = distance(event);
+ initialTouchX = midpoint(event, "x");
+ initialTouchY = midpoint(event, "y");
});
- element.addEventListener("touchend", (event: TouchEvent) => {
- if (event.touches.length == 2) return;
- pinching = false;
- })
- element.addEventListener("touchmove", (event: TouchEvent) => {
- if (!pinching) return;
+ canvas.addEventListener("touchmove", (event: TouchEvent) => {
+ if (!pinching) {
+ apply(currentZoom, [
+ initialX + (((event.touches[0].clientX - initialTouchX)/initialZoom)),
+ initialY + ((event.touches[0].clientY - initialTouchY)/initialZoom),
+ ]);
+ return;
+ }
+ if (event.touches.length < 2) return;
event.preventDefault();
const currentDistance = distance(event);
- const factor = currentDistance / initialDistance;
- apply(factor);
- })
-}
+ const midX = midpoint(event, "x");
+ const midY = midpoint(event, "y");
+ const ratio = currentDistance / initialDistance;
+ const difference = currentDistance - initialDistance;
+ apply(initialZoom * ratio, [initialX + (midX - difference - initialTouchX)/initialZoom, initialY + (midY - difference - initialTouchY)/initialZoom]);
+ });
+ canvas.addEventListener("wheel", (event: WheelEvent) => {
+ event.preventDefault();
+ if (!event.shiftKey) {
+ apply(currentZoom, [currentX - event.deltaX, currentY - event.deltaY]);
+ return;
+ };
+ apply(currentZoom + (event.deltaY < 0 ? 1 : -1) * 0.1, [initialX, initialY]);
+ });
+ canvas.addEventListener("scroll", (event: MouseEvent) => {
+ event.preventDefault();
+ });
+}
diff --git a/src/View/ChatPages/boardKanbanPage.tsx b/src/View/ChatPages/boardKanbanPage.tsx
index ef2a7c42..bbf8f994 100644
--- a/src/View/ChatPages/boardKanbanPage.tsx
+++ b/src/View/ChatPages/boardKanbanPage.tsx
@@ -1,6 +1,4 @@
import * as React from "bloatless-react";
-import * as Utility from "../../Model/Utility/utility";
-
import { ViewController } from "../viewController";
import { TaskViewModelToEntry } from "../Components/taskEntry";
import {
@@ -12,12 +10,13 @@ import { TaskCategoryBulkChangeViewModel } from "../../ViewModel/Utility/taskPro
import TaskViewModel from "../../ViewModel/Pages/taskViewModel";
import BoardViewModel from "../../ViewModel/Pages/boardViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
+import * as Utility from "../../Model/Utility/utility";
export function BoardKanbanPage(
coreViewModel: CoreViewModel,
boardViewModel: BoardViewModel,
) {
- const main = PropertyValueList(
+ return PropertyValueList(
"category",
(taskViewModel: TaskViewModel) => taskViewModel.task,
boardViewModel.filteredTaskViewModels,
@@ -43,14 +42,12 @@ export function BoardKanbanPage(
return (
);
},
);
- Utility.implementPinchZoom(main);
- return main;
}
function Column(
diff --git a/src/View/ChatPages/boardPage.tsx b/src/View/ChatPages/boardPage.tsx
index cf0b8f2b..8532e1d7 100644
--- a/src/View/ChatPages/boardPage.tsx
+++ b/src/View/ChatPages/boardPage.tsx
@@ -11,6 +11,7 @@ import BoardViewModel, {
BoardPageTypes,
} from "../../ViewModel/Pages/boardViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
+import * as Utility from "../../Model/Utility/utility";
export function BoardPage(
coreViewModel: CoreViewModel,
@@ -148,6 +149,7 @@ export function BoardPage(
+
{BoardSettingsModal(coreViewModel, boardViewModel)}
diff --git a/src/View/ChatPages/boardStatusGridPage.tsx b/src/View/ChatPages/boardStatusGridPage.tsx
index 1e3cfe0c..264af3c6 100644
--- a/src/View/ChatPages/boardStatusGridPage.tsx
+++ b/src/View/ChatPages/boardStatusGridPage.tsx
@@ -1,6 +1,4 @@
import * as React from "bloatless-react";
-import * as Utility from "../../Model/Utility/utility";
-
import { ViewController } from "../viewController";
import { TaskViewModelToEntry } from "../Components/taskEntry";
import {
@@ -17,6 +15,7 @@ import {
import TaskViewModel from "../../ViewModel/Pages/taskViewModel";
import BoardViewModel from "../../ViewModel/Pages/boardViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
+import * as Utility from "../../Model/Utility/utility";
export function BoardStatusGridPage(
coreViewModel: CoreViewModel,
@@ -42,8 +41,8 @@ export function BoardStatusGridPage(
return StatusNameCell(coreViewModel, statusName, index, boardViewModel);
};
- const main = (
-
+ return (
+
);
- Utility.implementPinchZoom(main);
- return main;
}
function StatusNameCell(
diff --git a/src/View/ChatPages/taskPage.css b/src/View/ChatPages/taskPage.css
index 4f6ec545..f85a3a45 100644
--- a/src/View/ChatPages/taskPage.css
+++ b/src/View/ChatPages/taskPage.css
@@ -3,6 +3,7 @@
max-width: 100%;
padding: 0px;
+ overflow: hidden;
}
#chat-page
@@ -24,16 +25,14 @@
padding: var(--content-padding);
}
-#chat-page > div > #main > #task-page .kanban-board-wrapper,
-#chat-page > div > #main > #task-page .status-page-content {
+#chat-page > div > #main > #task-page .zoom {
display: flex;
align-items: start;
gap: var(--large-gap);
- width: 100%;
- height: 100%;
+ width: auto;
+ height: auto;
- overflow: visible;
transform-origin: top left;
padding: var(--content-padding);
diff --git a/src/View/Modals/dataTransferModal.tsx b/src/View/Modals/dataTransferModal.tsx
index 76f54b5b..91acb5a2 100644
--- a/src/View/Modals/dataTransferModal.tsx
+++ b/src/View/Modals/dataTransferModal.tsx
@@ -24,14 +24,14 @@ export function DataTransferModalWrapper(
)}
{FileSelectionModal(coreViewModel, fileTransferViewModel)}
{TransferDataDisplayModal(coreViewModel, fileTransferViewModel)}
- {TransferDisplayModal(coreViewModel, fileTransferViewModel)}
- {TransferDataInputModal(coreViewModel, fileTransferViewModel)}
- {DataReceptionModal(coreViewModel, fileTransferViewModel)}
- {ExportFileSelectionModal(coreViewModel, fileTransferViewModel)}
- {ExportModal(coreViewModel, fileTransferViewModel)}
- {ImportModal(coreViewModel, fileTransferViewModel)}
- {ImportDecryptionDataModal(coreViewModel, fileTransferViewModel)}
-
+ {TransferDisplayModal(coreViewModel, fileTransferViewModel)}
+ {TransferDataInputModal(coreViewModel, fileTransferViewModel)}
+ {DataReceptionModal(coreViewModel, fileTransferViewModel)}
+ {ExportFileSelectionModal(coreViewModel, fileTransferViewModel)}
+ {ExportModal(coreViewModel, fileTransferViewModel)}
+ {ImportModal(coreViewModel, fileTransferViewModel)}
+ {ImportDecryptionDataModal(coreViewModel, fileTransferViewModel)}
+
);
}
@@ -42,30 +42,28 @@ function OptionEntry(
) {
const isSelected = new React.State(false);
if (fileTransferViewModel.selectedPaths.value.has(fileOption.path)) {
- isSelected.value = true;
+ isSelected.value = true;
}
isSelected.subscribeSilent((isSelected) => {
- if (isSelected == true) {
- fileTransferViewModel.selectedPaths.add(fileOption.path);
- } else {
- fileTransferViewModel.selectedPaths.remove(fileOption.path);
- }
+ if (isSelected == true) {
+ fileTransferViewModel.selectedPaths.add(fileOption.path);
+ } else {
+ fileTransferViewModel.selectedPaths.remove(fileOption.path);
+ }
});
function toggle() {
- isSelected.value = !isSelected.value;
+ isSelected.value = !isSelected.value;
}
return (
-
+
);
}
@@ -76,110 +74,110 @@ function DirectionSelectionModal(
fileTransferViewModel: FileTransferViewModel,
) {
const isPresented = React.createProxyState(
- [fileTransferViewModel.presentedModal],
- () =>
- fileTransferViewModel.presentedModal.value ==
- FileTransferModals.DirectionSelection,
+ [fileTransferViewModel.presentedModal],
+ () =>
+ fileTransferViewModel.presentedModal.value ==
+ FileTransferModals.DirectionSelection,
);
const isDisconnected = React.createProxyState(
- [connectionViewModel.isConnected],
- () => connectionViewModel.isConnected.value == false,
+ [connectionViewModel.isConnected],
+ () => connectionViewModel.isConnected.value == false,
);
return (
-
-
-
-
- {
- coreViewModel.translations.dataTransferModal
- .transferDataHeadline
- }
-
+
+
+
+
+ {
+ coreViewModel.translations.dataTransferModal
+ .transferDataHeadline
+ }
+
-
-
-
+
+
+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
);
}
@@ -188,89 +186,89 @@ function FileSelectionModal(
fileTransferViewModel: FileTransferViewModel,
) {
const OptionConverter: React.StateItemConverter
= (
- fileOption: FileTransferOption,
+ fileOption: FileTransferOption,
) => {
- return OptionEntry(fileOption, fileTransferViewModel);
+ return OptionEntry(fileOption, fileTransferViewModel);
};
// state
const isPresented = React.createProxyState(
- [fileTransferViewModel.presentedModal],
- () =>
- fileTransferViewModel.presentedModal.value ==
- FileTransferModals.FileSelection,
+ [fileTransferViewModel.presentedModal],
+ () =>
+ fileTransferViewModel.presentedModal.value ==
+ FileTransferModals.FileSelection,
);
return (
-
-
-
-
- {
- coreViewModel.translations.dataTransferModal
- .sendHeadline
- }
-
-
- {
- coreViewModel.translations.dataTransferModal
- .selectionDescription
- }
-
+
+
+
+
+ {
+ coreViewModel.translations.dataTransferModal
+ .sendHeadline
+ }
+
+
+ {
+ coreViewModel.translations.dataTransferModal
+ .selectionDescription
+ }
+
-
+
-
- {
- coreViewModel.translations.dataTransferModal
- .generalHeadline
- }
-
-
+
+ {
+ coreViewModel.translations.dataTransferModal
+ .generalHeadline
+ }
+
+
-
- {
- coreViewModel.translations.dataTransferModal
- .chatsHeadline
- }
-
-
-
-
-
-
-
-
-
-);
+
+ {
+ coreViewModel.translations.dataTransferModal
+ .chatsHeadline
+ }
+
+
+
+
+
+
+
+
+
+ );
}
function TransferDataDisplayModal(
@@ -278,82 +276,82 @@ function TransferDataDisplayModal(
fileTransferViewModel: FileTransferViewModel,
) {
const isPresented = React.createProxyState(
- [fileTransferViewModel.presentedModal],
- () =>
- fileTransferViewModel.presentedModal.value ==
- FileTransferModals.TransferDataDisplay,
+ [fileTransferViewModel.presentedModal],
+ () =>
+ fileTransferViewModel.presentedModal.value ==
+ FileTransferModals.TransferDataDisplay,
);
return (
-
-
-
-
- {
- coreViewModel.translations.dataTransferModal
- .sendHeadline
- }
-
+
+
+
+
+ {
+ coreViewModel.translations.dataTransferModal
+ .sendHeadline
+ }
+
-
- {
- coreViewModel.translations.dataTransferModal
- .dataEntryDescription
- }
-
+
+ {
+ coreViewModel.translations.dataTransferModal
+ .dataEntryDescription
+ }
+
-
+
-
-
-
forum
-
-
- {
- coreViewModel.translations
- .dataTransferModal
- .transferChannelHeadline
- }
-
-
-
-
-
-
key
-
-
- {
- coreViewModel.translations
- .dataTransferModal
- .transferKeyHeadline
- }
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
forum
+
+
+ {
+ coreViewModel.translations
+ .dataTransferModal
+ .transferChannelHeadline
+ }
+
+
+
+
+
+
key
+
+
+ {
+ coreViewModel.translations
+ .dataTransferModal
+ .transferKeyHeadline
+ }
+
+
+
+
+
+
+
+
+
+
+
+
);
}
@@ -362,77 +360,77 @@ function TransferDisplayModal(
fileTransferViewModel: FileTransferViewModel,
) {
const isPresented = React.createProxyState(
- [fileTransferViewModel.presentedModal],
- () =>
- fileTransferViewModel.presentedModal.value ==
- FileTransferModals.TransferDisplay,
+ [fileTransferViewModel.presentedModal],
+ () =>
+ fileTransferViewModel.presentedModal.value ==
+ FileTransferModals.TransferDisplay,
);
return (
-
-
-
-
- {
- coreViewModel.translations.dataTransferModal
- .transferDataHeadline
- }
-
+
+
+
+
+ {
+ coreViewModel.translations.dataTransferModal
+ .transferDataHeadline
+ }
+
-
+
-
- {
- coreViewModel.translations.dataTransferModal
- .allFilesSent
- }
-
+
+ {
+ coreViewModel.translations.dataTransferModal
+ .allFilesSent
+ }
+
-
+
-
-
-
-
-
-
-
-
-);
+
+
+
+
+
+
+
+
+ );
}
function TransferDataInputModal(
@@ -440,97 +438,97 @@ function TransferDataInputModal(
fileTransferViewModel: FileTransferViewModel,
) {
const isPresented = React.createProxyState(
- [fileTransferViewModel.presentedModal],
- () =>
- fileTransferViewModel.presentedModal.value ==
- FileTransferModals.TransferDataInput,
+ [fileTransferViewModel.presentedModal],
+ () =>
+ fileTransferViewModel.presentedModal.value ==
+ FileTransferModals.TransferDataInput,
);
return (
-
-
-
-
- {
- coreViewModel.translations.dataTransferModal
- .receiveHeadline
- }
-
+
+
+
+
+ {
+ coreViewModel.translations.dataTransferModal
+ .receiveHeadline
+ }
+
-
- {
- coreViewModel.translations.dataTransferModal
- .dataEntryInputDescription
- }
-
+
+ {
+ coreViewModel.translations.dataTransferModal
+ .dataEntryInputDescription
+ }
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
);
}
@@ -539,47 +537,47 @@ function DataReceptionModal(
fileTransferViewModel: FileTransferViewModel,
) {
const isPresented = React.createProxyState(
- [fileTransferViewModel.presentedModal],
- () =>
- fileTransferViewModel.presentedModal.value ==
- FileTransferModals.ReceptionDisplay,
+ [fileTransferViewModel.presentedModal],
+ () =>
+ fileTransferViewModel.presentedModal.value ==
+ FileTransferModals.ReceptionDisplay,
);
return (
-
-
-
-
- {
- coreViewModel.translations.dataTransferModal
- .receiveHeadline
- }
-
+
+
+
+
+ {
+ coreViewModel.translations.dataTransferModal
+ .receiveHeadline
+ }
+
-
+
-
+
-
-
-
-
-
-);
+
+
+
+
+
+ );
}
function ExportFileSelectionModal(
@@ -587,89 +585,89 @@ function ExportFileSelectionModal(
fileTransferViewModel: FileTransferViewModel,
) {
const OptionConverter: React.StateItemConverter = (
- fileOption: FileTransferOption,
+ fileOption: FileTransferOption,
) => {
- return OptionEntry(fileOption, fileTransferViewModel);
+ return OptionEntry(fileOption, fileTransferViewModel);
};
// state
const isPresented = React.createProxyState(
- [fileTransferViewModel.presentedModal],
- () =>
- fileTransferViewModel.presentedModal.value ==
- FileTransferModals.ExportFileSelection,
+ [fileTransferViewModel.presentedModal],
+ () =>
+ fileTransferViewModel.presentedModal.value ==
+ FileTransferModals.ExportFileSelection,
);
return (
-
-
-
-
- {
- coreViewModel.translations.dataTransferModal
- .exportHeadline
- }
-
-
- {
- coreViewModel.translations.dataTransferModal
- .exportSelectionDescription
- }
-
+
+
+
+
+ {
+ coreViewModel.translations.dataTransferModal
+ .exportHeadline
+ }
+
+
+ {
+ coreViewModel.translations.dataTransferModal
+ .exportSelectionDescription
+ }
+
-
+
-
- {
- coreViewModel.translations.dataTransferModal
- .generalHeadline
- }
-
-
+
+ {
+ coreViewModel.translations.dataTransferModal
+ .generalHeadline
+ }
+
+
-
- {
- coreViewModel.translations.dataTransferModal
- .chatsHeadline
- }
-
-
-
-
-
-
-
-
-
-);
+
+ {
+ coreViewModel.translations.dataTransferModal
+ .chatsHeadline
+ }
+
+
+
+
+
+
+
+
+
+ );
}
function ExportModal(
@@ -677,84 +675,82 @@ function ExportModal(
fileTransferViewModel: FileTransferViewModel,
) {
const isPresented = React.createProxyState(
- [fileTransferViewModel.presentedModal],
- () =>
- fileTransferViewModel.presentedModal.value ==
- FileTransferModals.Export,
+ [fileTransferViewModel.presentedModal],
+ () =>
+ fileTransferViewModel.presentedModal.value ==
+ FileTransferModals.Export,
);
return (
-
-
-
-
- {
- coreViewModel.translations.dataTransferModal
- .exportHeadline
- }
-
+
+
+
+
+ {
+ coreViewModel.translations.dataTransferModal
+ .exportHeadline
+ }
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
);
}
@@ -763,50 +759,57 @@ function ImportModal(
fileTransferViewModel: FileTransferViewModel,
) {
const isPresented = React.createProxyState(
- [fileTransferViewModel.presentedModal],
- () =>
- fileTransferViewModel.presentedModal.value ==
- FileTransferModals.ImportSelection,
+ [fileTransferViewModel.presentedModal],
+ () =>
+ fileTransferViewModel.presentedModal.value ==
+ FileTransferModals.ImportSelection,
);
return (
-
-
-
-
- {
- coreViewModel.translations.dataTransferModal
- .importHeadline
- }
-
+
+
+
+
+ {
+ coreViewModel.translations.dataTransferModal
+ .importHeadline
+ }
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
);
}
@@ -815,71 +818,73 @@ function ImportDecryptionDataModal(
fileTransferViewModel: FileTransferViewModel,
) {
const isPresented = React.createProxyState(
- [fileTransferViewModel.presentedModal],
- () =>
- fileTransferViewModel.presentedModal.value ==
- FileTransferModals.ImportDecryptData,
+ [fileTransferViewModel.presentedModal],
+ () =>
+ fileTransferViewModel.presentedModal.value ==
+ FileTransferModals.ImportDecryptData,
);
return (
-
-
-
-
- {
- coreViewModel.translations.dataTransferModal
- .importHeadline
- }
-
+
+
+
+
+ {
+ coreViewModel.translations.dataTransferModal
+ .importHeadline
+ }
+
-
-
-
+
+
+
-
- {coreViewModel.translations.dataTransferModal.incorrectPassphraseError}
-
-
-
-
-
-
-
-
+
+ {
+ coreViewModel.translations.dataTransferModal
+ .incorrectPassphraseError
+ }
+
+
+
+
+
+
+
+
);
}
diff --git a/src/View/translations.ts b/src/View/translations.ts
index d32a7ccd..13fe9493 100644
--- a/src/View/translations.ts
+++ b/src/View/translations.ts
@@ -145,14 +145,14 @@ const englishTranslations = {
filesReceivedCount: (count: number) => `Files processed: ${count}.`,
- //
-
- exportKey: "Encryption key",
- exportKeyConfirmation: "Confirm",
- downloadFileButton: "Download",
- importFileButton: "Import",
- decryptImportButton: "Decrypt",
- incorrectPassphraseError: "The encryption key is incorrect",
+ //
+
+ exportKey: "Encryption key",
+ exportKeyConfirmation: "Confirm",
+ downloadFileButton: "Download",
+ importFileButton: "Import",
+ decryptImportButton: "Decrypt",
+ incorrectPassphraseError: "The encryption key is incorrect",
},
storage: {
diff --git a/src/ViewModel/Global/coreViewModel.ts b/src/ViewModel/Global/coreViewModel.ts
index ffefdf32..7fc414e9 100644
--- a/src/ViewModel/Global/coreViewModel.ts
+++ b/src/ViewModel/Global/coreViewModel.ts
@@ -9,7 +9,7 @@ import ConnectionModel from "../../Model/Global/connectionModel";
import ChatListModel from "../../Model/Chat/chatListModel";
export default class CoreViewModel {
- readonly BUILD = "Build 26.08.30.C";
+ readonly BUILD = "Build 26.08.30.D";
translations: Translations;
diff --git a/src/ViewModel/Global/fileTransferViewModel.ts b/src/ViewModel/Global/fileTransferViewModel.ts
index cf9a1ba7..16c2d2d3 100644
--- a/src/ViewModel/Global/fileTransferViewModel.ts
+++ b/src/ViewModel/Global/fileTransferViewModel.ts
@@ -54,7 +54,7 @@ export default class FileTransferViewModel extends Context {
exportKey: React.State = new React.State("");
exportKeyConfirmation: React.State = new React.State("");
- importedFile: React.State = new React.State(undefined);
+ importedFile: React.State = new React.State(undefined);
importedFileString: React.State = new React.State("");
importKey: React.State = new React.State("");
isImportKeyCorrect: React.State = new React.State(true);
@@ -71,21 +71,20 @@ export default class FileTransferViewModel extends Context {
this.receivingTransferChannel.value == "" ||
this.receivingTransferKey.value == "",
);
-
+
cannotExport: React.State = React.createProxyState(
[this.exportKey, this.exportKeyConfirmation],
() =>
- this.exportKey.value == "" || this.exportKey.value != this.exportKeyConfirmation.value
+ this.exportKey.value == "" ||
+ this.exportKey.value != this.exportKeyConfirmation.value,
);
cannotImport: React.State = React.createProxyState(
[this.importedFile],
- () =>
- this.importedFile.value == undefined
+ () => this.importedFile.value == undefined,
);
cannotDecryptImport: React.State = React.createProxyState(
[this.importKey],
- () =>
- this.importKey.value == ""
+ () => this.importKey.value == "",
);
// handlers
@@ -136,142 +135,149 @@ export default class FileTransferViewModel extends Context {
};
downloadFile = async (): Promise => {
- const date = new Date().toISOString().split("T")[0];
+ const date = new Date().toISOString().split("T")[0];
- const backup: Blob = await this.coreViewModel.fileTransferModel.generateBackup(this.selectedPaths.value.values(), this.exportKey.value);
- const anchor = document.createElement("a");
- anchor.href = window.URL.createObjectURL(backup);
- anchor.download = `comms-${date}.bak`;
- anchor.click();
- }
+ const backup: Blob =
+ await this.coreViewModel.fileTransferModel.generateBackup(
+ this.selectedPaths.value.values(),
+ this.exportKey.value,
+ );
+ const anchor = document.createElement("a");
+ anchor.href = window.URL.createObjectURL(backup);
+ anchor.download = `comms-${date}.bak`;
+ anchor.click();
+ };
updateImportSelection = (): void => {
- const input = document.getElementById("file-transfer-input");
- if (!input) return;
- if (!(input instanceof HTMLInputElement)) return;
+ const input = document.getElementById("file-transfer-input");
+ if (!input) return;
+ if (!(input instanceof HTMLInputElement)) return;
- const file = input.files[0];
- this.importedFile.value = file;
- }
+ const file = input.files[0];
+ this.importedFile.value = file;
+ };
importFile = (): void => {
- const file = this.importedFile.value;
- if (!file) return;
+ const file = this.importedFile.value;
+ if (!file) return;
- const reader = new FileReader();
- reader.readAsText(file, "utf8");
- reader.onload = () => {
- const result = reader.result;
- this.importedFileString.value = result.toString();
- this.showImportDecryptDataModal();
- }
- }
+ const reader = new FileReader();
+ reader.readAsText(file, "utf8");
+ reader.onload = () => {
+ const result = reader.result;
+ this.importedFileString.value = result.toString();
+ this.showImportDecryptDataModal();
+ };
+ };
decryptImport = async (): Promise => {
- const fileString = this.importedFileString.value;
- const key = this.importKey.value;
- if (!fileString || !key) return;
+ const fileString = this.importedFileString.value;
+ const key = this.importKey.value;
+ if (!fileString || !key) return;
- this.cannotDecryptImport.value = true;
- try {
- await this.coreViewModel.fileTransferModel.handleBackupFile(fileString, key);
- window.location.reload();
- } catch (e) {
- console.error(e);
- this.isImportKeyCorrect.value = false;
- this.cannotDecryptImport.value = false;
- }
- }
+ this.cannotDecryptImport.value = true;
+ try {
+ await this.coreViewModel.fileTransferModel.handleBackupFile(
+ fileString,
+ key,
+ );
+ window.location.reload();
+ } catch (e) {
+ console.error(e);
+ this.isImportKeyCorrect.value = false;
+ this.cannotDecryptImport.value = false;
+ }
+ };
// view
showDirectionSelectionModal = (): void => {
- this.coreViewModel.context = this;
- this.presentedModal.value = FileTransferModals.DirectionSelection;
- this.getOptions();
+ this.coreViewModel.context = this;
+ this.presentedModal.value = FileTransferModals.DirectionSelection;
+ this.getOptions();
};
showFileSelectionModal = (): void => {
- this.presentedModal.value = FileTransferModals.FileSelection;
+ this.presentedModal.value = FileTransferModals.FileSelection;
};
showTransferDataModal = (): void => {
- this.presentedModal.value = FileTransferModals.TransferDataDisplay;
- this.getTransferData();
- this.coreViewModel.fileTransferModel.prepareToSend();
+ this.presentedModal.value = FileTransferModals.TransferDataDisplay;
+ this.getTransferData();
+ this.coreViewModel.fileTransferModel.prepareToSend();
};
initiateTransfer = (): void => {
- this.presentedModal.value = FileTransferModals.TransferDisplay;
- this.didNotFinishSending.value = true;
- this.filePathsSent.clear();
+ this.presentedModal.value = FileTransferModals.TransferDisplay;
+ this.didNotFinishSending.value = true;
+ this.filePathsSent.clear();
- this.coreViewModel.fileTransferModel.sendFiles(
- this.selectedPaths.value.values(),
- (path: string) => {
- this.filePathsSent.add(path);
- },
- );
+ this.coreViewModel.fileTransferModel.sendFiles(
+ this.selectedPaths.value.values(),
+ (path: string) => {
+ this.filePathsSent.add(path);
+ },
+ );
- this.didNotFinishSending.value = false;
+ this.didNotFinishSending.value = false;
};
showTransferDataInputModal = (): void => {
- this.presentedModal.value = FileTransferModals.TransferDataInput;
+ this.presentedModal.value = FileTransferModals.TransferDataInput;
};
showExportSelectionModal = (): void => {
- this.presentedModal.value = FileTransferModals.ExportFileSelection;
+ this.presentedModal.value = FileTransferModals.ExportFileSelection;
};
showExportModal = (): void => {
- this.presentedModal.value = FileTransferModals.Export;
+ this.presentedModal.value = FileTransferModals.Export;
};
showImportModal = (): void => {
- this.presentedModal.value = FileTransferModals.ImportSelection;
+ this.presentedModal.value = FileTransferModals.ImportSelection;
};
showImportDecryptDataModal = (): void => {
- this.presentedModal.value = FileTransferModals.ImportDecryptData;
+ this.presentedModal.value = FileTransferModals.ImportDecryptData;
};
prepareReceivingData = (): void => {
- if (this.cannotPrepareToReceive.value == true) return;
- this.presentedModal.value = FileTransferModals.ReceptionDisplay;
- this.filePathsReceived.clear();
+ if (this.cannotPrepareToReceive.value == true) return;
+ this.presentedModal.value = FileTransferModals.ReceptionDisplay;
+ this.filePathsReceived.clear();
- const transferData: TransferData = {
- channel: this.receivingTransferChannel.value,
- key: this.receivingTransferKey.value,
- };
- this.coreViewModel.fileTransferModel.prepareToReceive(transferData);
+ const transferData: TransferData = {
+ channel: this.receivingTransferChannel.value,
+ key: this.receivingTransferKey.value,
+ };
+ this.coreViewModel.fileTransferModel.prepareToReceive(transferData);
};
// exit
close = (): void => {
- this.coreViewModel.closeContext(this.contextId);
+ this.coreViewModel.closeContext(this.contextId);
};
handleContextClose = (): void => {
- this.presentedModal.value = undefined;
+ this.presentedModal.value = undefined;
};
// init
constructor(public readonly coreViewModel: CoreViewModel) {
- super("file-transfer");
+ super("file-transfer");
- this.coreViewModel.fileTransferModel.fileHandlerManager.setHandler(
- "file-transfer-view-model",
- this.handleReceivedFile,
- );
+ this.coreViewModel.fileTransferModel.fileHandlerManager.setHandler(
+ "file-transfer-view-model",
+ this.handleReceivedFile,
+ );
- this.coreViewModel.fileTransferModel.readyToSendHandlerManager.setHandler(
- "file-transfer-view-model",
- () => this.initiateTransfer(),
- );
+ this.coreViewModel.fileTransferModel.readyToSendHandlerManager.setHandler(
+ "file-transfer-view-model",
+ () => this.initiateTransfer(),
+ );
- // keystrokes
- this.registerKeyStroke(CommonKeys.CloseOrCancel, this.close);
+ // keystrokes
+ this.registerKeyStroke(CommonKeys.CloseOrCancel, this.close);
}
}
@@ -283,18 +289,18 @@ export interface FileTransferOption {
export enum FileTransferModals {
DirectionSelection,
- // sending
- FileSelection,
- TransferDataDisplay,
- TransferDisplay,
+ // sending
+ FileSelection,
+ TransferDataDisplay,
+ TransferDisplay,
- // receiving
- TransferDataInput,
- ReceptionDisplay,
+ // receiving
+ TransferDataInput,
+ ReceptionDisplay,
- // export
- ExportFileSelection,
- Export,
- ImportSelection,
- ImportDecryptData,
+ // export
+ ExportFileSelection,
+ Export,
+ ImportSelection,
+ ImportDecryptData,
}
diff --git a/src/index.tsx b/src/index.tsx
index bcd2f431..a44a0c5e 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -2,7 +2,6 @@ import * as React from "bloatless-react";
import "./colors.css";
import "./coloredTile.css";
import "./base.css";
-import * as Utility from "./Model/Utility/utility";
import HomeViewModel from "./ViewModel/Pages/homeViewModel";
import StorageViewModel from "./ViewModel/Global/storageViewModel";
import SettingsViewModel from "./ViewModel/Global/settingsViewModel";
@@ -17,6 +16,7 @@ import { SettingsModal } from "./View/Modals/settingsModal";
import { DataTransferModalWrapper } from "./View/Modals/dataTransferModal";
import { ConnectionModal } from "./View/Modals/connectionModal";
import v1Upgrader from "./Upgrader/v1";
+import * as Utility from "./Model/Utility/utility";
import StorageModel from "./Model/Global/storageModel";
import SettingsModel from "./Model/Global/settingsModel";
import FileTransferModel from "./Model/Global/fileTransferModel";
@@ -100,3 +100,4 @@ document
StorageModal(coreViewModel, storageViewModel),
SettingsModal(coreViewModel, settingsViewModel),
);
+Utility.implementPinchZoom(".zoom");