Files
CT/src/View/Modals/dataTransferModal.tsx
T

636 lines
23 KiB
TypeScript
Raw Normal View History

2024-07-27 19:13:59 +02:00
import * as React from "bloatless-react";
2026-04-18 11:55:01 +00:00
import { ViewController } from "../viewController";
import { StringToTextSpan } from "../Components/textSpan";
2024-07-27 19:13:59 +02:00
import FileTransferViewModel, {
2026-04-08 14:02:12 +00:00
FileTransferModals,
2026-04-01 08:29:39 +00:00
FileTransferOption,
2024-07-27 19:13:59 +02:00
} from "../../ViewModel/Global/fileTransferViewModel";
2026-04-18 11:55:01 +00:00
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import ConnectionViewModel from "../../ViewModel/Global/connectionViewModel";
2024-07-27 19:13:59 +02:00
import StorageModel from "../../Model/Global/storageModel";
export function DataTransferModalWrapper(
coreViewModel: CoreViewModel,
2026-04-01 08:29:39 +00:00
connectionViewModel: ConnectionViewModel,
fileTransferViewModel: FileTransferViewModel,
2024-07-27 19:13:59 +02:00
) {
2026-04-01 08:29:39 +00:00
return (
<div>
{DirectionSelectionModal(
coreViewModel,
2026-04-01 08:29:39 +00:00
connectionViewModel,
fileTransferViewModel,
)}
{FileSelectionModal(coreViewModel, fileTransferViewModel)}
{TransferDataDisplayModal(coreViewModel, fileTransferViewModel)}
{TransferDisplayModal(coreViewModel, fileTransferViewModel)}
{TransferDataInputModal(coreViewModel, fileTransferViewModel)}
{DataReceptionModal(coreViewModel, fileTransferViewModel)}
{ImportModal(coreViewModel, fileTransferViewModel)}
2026-04-01 08:29:39 +00:00
</div>
);
}
function DirectionSelectionModal(
coreViewModel: CoreViewModel,
2026-04-01 08:29:39 +00:00
connectionViewModel: ConnectionViewModel,
fileTransferViewModel: FileTransferViewModel,
) {
2026-04-01 08:29:39 +00:00
const isPresented = React.createProxyState(
[fileTransferViewModel.presentedModal],
() =>
fileTransferViewModel.presentedModal.value ==
2026-04-08 14:02:12 +00:00
FileTransferModals.DirectionSelection,
2026-04-01 08:29:39 +00:00
);
const isDisconnected = React.createProxyState(
[connectionViewModel.isConnected],
() => connectionViewModel.isConnected.value == false,
);
return (
<div class="modal" toggle:open={isPresented}>
<div>
<main>
<h2>
{
coreViewModel.translations.dataTransferModal
.transferDataHeadline
}
2026-04-01 08:29:39 +00:00
</h2>
<p
class="error"
toggle:hidden={connectionViewModel.isConnected}
>
{
coreViewModel.translations.dataTransferModal
.notConnectedError
}
2026-04-01 08:29:39 +00:00
</p>
<div
class="flex-column gap content-margin-bottom"
toggle:hidden={isDisconnected}
>
<button
class="tile"
on:click={
fileTransferViewModel.showFileSelectionModal
}
>
2026-08-29 02:34:20 +02:00
<span class="icon">share_windows</span>
2026-04-01 08:29:39 +00:00
<div>
<b>
{
coreViewModel.translations
.dataTransferModal
2026-04-01 08:29:39 +00:00
.fromThisDeviceButton
}
</b>
</div>
<span class="icon">arrow_forward</span>
</button>
<button
class="tile"
on:click={
fileTransferViewModel.showTransferDataInputModal
}
>
2026-08-29 02:34:20 +02:00
<span class="icon">cloud_download</span>
2026-04-01 08:29:39 +00:00
<div>
<b>
{
coreViewModel.translations
.dataTransferModal
2026-04-01 08:29:39 +00:00
.toThisDeviceButton
}
</b>
</div>
<span class="icon">arrow_forward</span>
</button>
<hr></hr>
<button
class="tile"
on:click={fileTransferViewModel.showImportModal}
>
<span class="icon">file_save</span>
<div>
<b>
{
coreViewModel.translations
.dataTransferModal.exportButton
}
</b>
</div>
<span class="icon">arrow_forward</span>
2026-04-01 08:29:39 +00:00
</button>
2026-08-29 02:34:20 +02:00
<button
class="tile"
on:click={fileTransferViewModel.showImportModal}
2026-08-29 02:34:20 +02:00
>
<span class="icon">upload_file</span>
2026-08-29 02:34:20 +02:00
<div>
<b>
{
coreViewModel.translations
.dataTransferModal.importButton
2026-08-29 02:34:20 +02:00
}
</b>
</div>
<span class="icon">arrow_forward</span>
</button>
2026-04-01 08:29:39 +00:00
</div>
</main>
2026-04-14 17:19:35 +00:00
<button on:click={fileTransferViewModel.close}>
{coreViewModel.translations.general.closeButton}
2026-04-01 08:29:39 +00:00
<span class="icon">close</span>
</button>
</div>
</div>
);
}
function FileSelectionModal(
coreViewModel: CoreViewModel,
fileTransferViewModel: FileTransferViewModel,
) {
2026-04-01 08:29:39 +00:00
// option
const OptionConverter: React.StateItemConverter<FileTransferOption> = (
fileOption: FileTransferOption,
) => {
return OptionEntry(fileOption, fileTransferViewModel);
};
function OptionEntry(
fileOption: FileTransferOption,
fileTransferViewModel: FileTransferViewModel,
) {
const isSelected = new React.State(false);
if (fileTransferViewModel.selectedPaths.value.has(fileOption.path)) {
isSelected.value = true;
}
isSelected.subscribeSilent((isSelected) => {
if (isSelected == true) {
fileTransferViewModel.selectedPaths.add(fileOption.path);
} else {
fileTransferViewModel.selectedPaths.remove(fileOption.path);
}
});
function toggle() {
isSelected.value = !isSelected.value;
}
return (
<button class="tile" toggle:selected={isSelected} on:click={toggle}>
<div>
<b class="ellipsis">{fileOption.label}</b>
<span class="secondary ellipsis">
{StorageModel.pathComponentsToString(
...fileOption.path,
)}
</span>
</div>
</button>
);
}
2026-04-01 08:29:39 +00:00
// state
const isPresented = React.createProxyState(
[fileTransferViewModel.presentedModal],
() =>
fileTransferViewModel.presentedModal.value ==
2026-04-08 14:02:12 +00:00
FileTransferModals.FileSelection,
2026-04-01 08:29:39 +00:00
);
return (
2026-04-01 08:29:39 +00:00
<div class="modal" toggle:open={isPresented}>
<div>
<main>
<h2>
{
coreViewModel.translations.dataTransferModal
.sendHeadline
}
2026-04-01 08:29:39 +00:00
</h2>
<span class="secondary">
{
coreViewModel.translations.dataTransferModal
.selectionDescription
}
2026-04-01 08:29:39 +00:00
</span>
<hr></hr>
<h3>
{
coreViewModel.translations.dataTransferModal
.generalHeadline
}
</h3>
2026-04-01 08:29:39 +00:00
<div
class="flex-column gap content-margin-bottom"
children:append={[
fileTransferViewModel.generalFileOptions,
OptionConverter,
]}
></div>
<h3>
{
coreViewModel.translations.dataTransferModal
.chatsHeadline
}
</h3>
2026-04-01 08:29:39 +00:00
<div
class="flex-column gap"
children:append={[
fileTransferViewModel.chatFileOptions,
OptionConverter,
]}
></div>
</main>
<div class="flex-row width-100">
<button
class="flex"
on:click={
fileTransferViewModel.showDirectionSelectionModal
}
>
{coreViewModel.translations.general.backButton}
2026-04-01 08:29:39 +00:00
</button>
<button
class="primary flex"
on:click={fileTransferViewModel.showTransferDataModal}
toggle:disabled={
fileTransferViewModel.hasNoPathsSelected
}
>
{coreViewModel.translations.general.continueButton}
2026-04-01 08:29:39 +00:00
<span class="icon">arrow_forward</span>
</button>
</div>
</div>
</div>
);
2024-07-27 19:13:59 +02:00
}
2024-07-28 00:25:51 +02:00
function TransferDataDisplayModal(
coreViewModel: CoreViewModel,
2026-04-01 08:29:39 +00:00
fileTransferViewModel: FileTransferViewModel,
2024-07-28 00:25:51 +02:00
) {
2026-04-01 08:29:39 +00:00
const isPresented = React.createProxyState(
[fileTransferViewModel.presentedModal],
() =>
fileTransferViewModel.presentedModal.value ==
2026-04-08 14:02:12 +00:00
FileTransferModals.TransferDataDisplay,
2026-04-01 08:29:39 +00:00
);
return (
<div class="modal" toggle:open={isPresented}>
<div>
<main>
<h2>
{
coreViewModel.translations.dataTransferModal
.sendHeadline
}
2026-04-01 08:29:39 +00:00
</h2>
<span class="secondary">
{
coreViewModel.translations.dataTransferModal
.dataEntryDescription
}
2026-04-01 08:29:39 +00:00
</span>
<hr></hr>
<div class="flex-column gap content-margin-bottom">
<div class="tile">
<span class="icon">forum</span>
<div>
<span class="secondary">
{
coreViewModel.translations
.dataTransferModal
2026-04-01 08:29:39 +00:00
.transferChannelHeadline
}
</span>
<b
subscribe:innerText={
fileTransferViewModel.transferChannel
}
></b>
</div>
</div>
<div class="tile">
<span class="icon">key</span>
<div>
<span class="secondary">
{
coreViewModel.translations
.dataTransferModal
2026-04-01 08:29:39 +00:00
.transferKeyHeadline
}
</span>
<b
subscribe:innerText={
fileTransferViewModel.transferKey
}
></b>
</div>
</div>
</div>
2026-04-01 08:29:39 +00:00
</main>
<div class="flex-row width-100">
<button
class="flex"
on:click={fileTransferViewModel.showFileSelectionModal}
>
{coreViewModel.translations.general.backButton}
2026-04-01 08:29:39 +00:00
</button>
2026-04-06 15:50:13 +00:00
<button disabled class="flex">
{coreViewModel.translations.general.waitingLabel}
2026-04-01 08:29:39 +00:00
</button>
</div>
2024-07-28 00:25:51 +02:00
</div>
</div>
2026-04-01 08:29:39 +00:00
);
2024-07-28 00:25:51 +02:00
}
2024-07-28 02:27:09 +02:00
function TransferDisplayModal(
coreViewModel: CoreViewModel,
fileTransferViewModel: FileTransferViewModel,
) {
2026-04-01 08:29:39 +00:00
const isPresented = React.createProxyState(
[fileTransferViewModel.presentedModal],
() =>
fileTransferViewModel.presentedModal.value ==
2026-04-08 14:02:12 +00:00
FileTransferModals.TransferDisplay,
2026-04-01 08:29:39 +00:00
);
return (
<div class="modal" toggle:open={isPresented}>
<div>
<main>
<h2>
{
coreViewModel.translations.dataTransferModal
.transferDataHeadline
}
2026-04-01 08:29:39 +00:00
</h2>
<p
class="secondary"
subscribe:innerText={
fileTransferViewModel.filesSentText
}
></p>
<p
class="secondary"
toggle:hidden={
fileTransferViewModel.didNotFinishSending
}
>
{
coreViewModel.translations.dataTransferModal
.allFilesSent
}
2026-04-01 08:29:39 +00:00
</p>
<hr></hr>
<div
class="tile flex-column align-start"
children:append={[
fileTransferViewModel.filePathsSent,
StringToTextSpan,
]}
></div>
</main>
<div class="flex-row width-100">
<button
class="flex"
on:click={fileTransferViewModel.initiateTransfer}
>
{
coreViewModel.translations.dataTransferModal
.sendAgainButton
}
2026-04-01 08:29:39 +00:00
<span class="icon">restart_alt</span>
</button>
<button
class="flex"
2026-04-14 17:19:35 +00:00
on:click={fileTransferViewModel.close}
2026-04-01 08:29:39 +00:00
toggle:disabled={
fileTransferViewModel.didNotFinishSending
}
>
{coreViewModel.translations.general.closeButton}
2026-04-01 08:29:39 +00:00
<span class="icon">close</span>
</button>
</div>
</div>
2024-07-28 19:32:04 +02:00
</div>
2026-04-01 08:29:39 +00:00
);
2024-07-28 02:27:09 +02:00
}
2024-07-28 03:46:08 +02:00
function TransferDataInputModal(
coreViewModel: CoreViewModel,
fileTransferViewModel: FileTransferViewModel,
) {
2026-04-01 08:29:39 +00:00
const isPresented = React.createProxyState(
[fileTransferViewModel.presentedModal],
() =>
fileTransferViewModel.presentedModal.value ==
2026-04-08 14:02:12 +00:00
FileTransferModals.TransferDataInput,
2026-04-01 08:29:39 +00:00
);
return (
<div class="modal" toggle:open={isPresented}>
<div>
<main>
<h2>
{
coreViewModel.translations.dataTransferModal
.receiveHeadline
}
2026-04-01 08:29:39 +00:00
</h2>
<span class="secondary">
{
coreViewModel.translations.dataTransferModal
2026-04-01 08:29:39 +00:00
.dataEntryInputDescription
}
</span>
<hr></hr>
<div class="flex-column gap content-margin-bottom">
<label class="tile">
<span class="icon">forum</span>
<div>
<span class="secondary">
{
coreViewModel.translations
.dataTransferModal
2026-04-01 08:29:39 +00:00
.transferChannelHeadline
}
</span>
<input
2026-04-13 11:23:17 +00:00
on:enter={
fileTransferViewModel.prepareReceivingData
}
2026-04-01 08:29:39 +00:00
bind:value={
fileTransferViewModel.receivingTransferChannel
}
></input>
</div>
</label>
<label class="tile">
<span class="icon">key</span>
<div>
<span class="secondary">
{
coreViewModel.translations
.dataTransferModal
2026-04-01 08:29:39 +00:00
.transferKeyHeadline
}
</span>
<input
2026-04-13 11:23:17 +00:00
on:enter={
fileTransferViewModel.prepareReceivingData
}
2026-04-01 08:29:39 +00:00
bind:value={
fileTransferViewModel.receivingTransferKey
}
></input>
</div>
</label>
</div>
</main>
<div class="flex-row width-100">
<button
class="flex"
on:click={
fileTransferViewModel.showDirectionSelectionModal
}
>
{coreViewModel.translations.general.backButton}
2026-04-01 08:29:39 +00:00
</button>
<button
class="primary flex"
on:click={fileTransferViewModel.prepareReceivingData}
toggle:disabled={
fileTransferViewModel.cannotPrepareToReceive
}
>
{coreViewModel.translations.general.continueButton}
2026-04-01 08:29:39 +00:00
<span class="icon">arrow_forward</span>
</button>
</div>
</div>
2024-07-28 03:46:08 +02:00
</div>
2026-04-01 08:29:39 +00:00
);
2024-07-28 03:46:08 +02:00
}
function DataReceptionModal(
coreViewModel: CoreViewModel,
fileTransferViewModel: FileTransferViewModel,
) {
2026-04-01 08:29:39 +00:00
const isPresented = React.createProxyState(
[fileTransferViewModel.presentedModal],
() =>
fileTransferViewModel.presentedModal.value ==
2026-04-08 14:02:12 +00:00
FileTransferModals.ReceptionDisplay,
2026-04-01 08:29:39 +00:00
);
return (
<div class="modal" toggle:open={isPresented}>
<div>
<main>
<h2>
{
coreViewModel.translations.dataTransferModal
.receiveHeadline
}
</h2>
<p
class="secondary"
subscribe:innerText={
fileTransferViewModel.filesReceivedText
}
></p>
<hr></hr>
<div
class="tile flex-column align-start"
children:append={[
fileTransferViewModel.filePathsReceived,
StringToTextSpan,
]}
></div>
</main>
<button on:click={ViewController.reload}>
{coreViewModel.translations.general.reloadAppButton}
<span class="icon">refresh</span>
</button>
</div>
</div>
);
}
function ImportModal(
coreViewModel: CoreViewModel,
fileTransferViewModel: FileTransferViewModel,
) {
const isPresented = React.createProxyState(
[fileTransferViewModel.presentedModal],
() =>
fileTransferViewModel.presentedModal.value ==
FileTransferModals.ImportModal,
);
return (
<div class="modal" toggle:open={isPresented}>
<div>
<main>
<h2>
{
coreViewModel.translations.dataTransferModal
.importHeadline
}
2026-04-01 08:29:39 +00:00
</h2>
<p
class="secondary"
subscribe:innerText={
fileTransferViewModel.filesReceivedText
}
></p>
<hr></hr>
<div
class="tile flex-column align-start"
children:append={[
fileTransferViewModel.filePathsReceived,
StringToTextSpan,
]}
></div>
</main>
2026-04-15 12:47:10 +00:00
<button on:click={ViewController.reload}>
{coreViewModel.translations.general.reloadAppButton}
2026-04-01 08:29:39 +00:00
<span class="icon">refresh</span>
</button>
</div>
</div>
);
2024-07-28 03:46:08 +02:00
}