Fixed some minor transfer bugs as well added some more features required for the native clients file transfer
parent
52d998000d
commit
5af68c0a1c
|
@ -526,6 +526,10 @@ export class FileManager {
|
||||||
|
|
||||||
const initializeCallback = async () => {
|
const initializeCallback = async () => {
|
||||||
try {
|
try {
|
||||||
|
transfer.target = await transfer.targetSupplier(transfer);
|
||||||
|
if(!transfer.target)
|
||||||
|
throw tr("Failed to create transfer target");
|
||||||
|
|
||||||
await this.connectionHandler.serverConnection.send_command("ftinitdownload", {
|
await this.connectionHandler.serverConnection.send_command("ftinitdownload", {
|
||||||
"path": options.path,
|
"path": options.path,
|
||||||
"name": options.name,
|
"name": options.name,
|
||||||
|
|
|
@ -47,7 +47,8 @@ export type TransferSourceSupplier = (transfer: FileUploadTransfer) => Promise<T
|
||||||
/* Transfer target types */
|
/* Transfer target types */
|
||||||
export enum TransferTargetType {
|
export enum TransferTargetType {
|
||||||
RESPONSE,
|
RESPONSE,
|
||||||
DOWNLOAD
|
DOWNLOAD,
|
||||||
|
FILE
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class TransferTarget {
|
export abstract class TransferTarget {
|
||||||
|
@ -72,6 +73,18 @@ export abstract class ResponseTransferTarget extends TransferTarget {
|
||||||
abstract hasResponse() : boolean;
|
abstract hasResponse() : boolean;
|
||||||
abstract getResponse() : Response;
|
abstract getResponse() : Response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export abstract class FileTransferTarget extends TransferTarget {
|
||||||
|
protected constructor() {
|
||||||
|
super(TransferTargetType.FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract getFilePath() : string;
|
||||||
|
|
||||||
|
abstract hasFileName() : boolean;
|
||||||
|
abstract getFileName() : string;
|
||||||
|
}
|
||||||
|
|
||||||
export type TransferTargetSupplier = (transfer: FileDownloadTransfer) => Promise<TransferTarget>;
|
export type TransferTargetSupplier = (transfer: FileDownloadTransfer) => Promise<TransferTarget>;
|
||||||
|
|
||||||
export enum FileTransferState {
|
export enum FileTransferState {
|
||||||
|
@ -134,7 +147,7 @@ export interface TransferInitializeError {
|
||||||
export interface TransferConnectError {
|
export interface TransferConnectError {
|
||||||
error: "connection";
|
error: "connection";
|
||||||
|
|
||||||
reason: "missing-provider" | "provider-initialize-error" | "network-error";
|
reason: "missing-provider" | "provider-initialize-error" | "handle-initialize-error" | "network-error";
|
||||||
extraMessage?: string;
|
extraMessage?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,6 +423,7 @@ export abstract class TransferProvider {
|
||||||
|
|
||||||
async createResponseTarget() : Promise<ResponseTransferTarget> { throw tr("response target isn't supported"); }
|
async createResponseTarget() : Promise<ResponseTransferTarget> { throw tr("response target isn't supported"); }
|
||||||
async createDownloadTarget(filename?: string) : Promise<DownloadTransferTarget> { throw tr("download target isn't supported"); }
|
async createDownloadTarget(filename?: string) : Promise<DownloadTransferTarget> { throw tr("download target isn't supported"); }
|
||||||
|
async createFileTarget(path?: string, filename?: string) : Promise<FileTransferTarget> { throw tr("file target isn't supported"); }
|
||||||
|
|
||||||
async createBufferSource(buffer: ArrayBuffer) : Promise<BufferTransferSource> { throw tr("buffer source isn't supported"); }
|
async createBufferSource(buffer: ArrayBuffer) : Promise<BufferTransferSource> { throw tr("buffer source isn't supported"); }
|
||||||
async createTextSource(text: string) : Promise<TextTransferSource> { throw tr("text source isn't supported"); };
|
async createTextSource(text: string) : Promise<TextTransferSource> { throw tr("text source isn't supported"); };
|
||||||
|
|
|
@ -219,7 +219,7 @@ export namespace CryptoHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TeaSpeakHandshakeHandler extends AbstractHandshakeIdentityHandler {
|
export class TeaSpeakHandshakeHandler extends AbstractHandshakeIdentityHandler {
|
||||||
identity: TeaSpeakIdentity;
|
identity: TeaSpeakIdentity;
|
||||||
handler: HandshakeCommandHandler<TeaSpeakHandshakeHandler>;
|
handler: HandshakeCommandHandler<TeaSpeakHandshakeHandler>;
|
||||||
|
|
||||||
|
|
|
@ -360,6 +360,12 @@ export class Settings extends StaticSettings {
|
||||||
description: "Show finished file transfers in the file transfer list"
|
description: "Show finished file transfers in the file transfer list"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static readonly KEY_TRANSFER_DOWNLOAD_FOLDER: SettingsKey<string> = {
|
||||||
|
key: "transfer_download_folder",
|
||||||
|
description: "The download folder for the file transfer downloads",
|
||||||
|
/* default_value: <users download directory> */
|
||||||
|
};
|
||||||
|
|
||||||
static readonly FN_INVITE_LINK_SETTING: (name: string) => SettingsKey<string> = name => {
|
static readonly FN_INVITE_LINK_SETTING: (name: string) => SettingsKey<string> = name => {
|
||||||
return {
|
return {
|
||||||
key: 'invite_link_setting_' + name
|
key: 'invite_link_setting_' + name
|
||||||
|
|
|
@ -426,7 +426,7 @@ const FileSize = (props: { path: string, events: Registry<FileBrowserEvents>, fi
|
||||||
setSize(event.fileSize);
|
setSize(event.fileSize);
|
||||||
});
|
});
|
||||||
|
|
||||||
if(size < 0 && props.file.size < 0)
|
if(size < 0 && (props.file.size < 0 || typeof props.file.size === "undefined"))
|
||||||
return <a key={"size-invalid"}><Translatable>unknown</Translatable></a>;
|
return <a key={"size-invalid"}><Translatable>unknown</Translatable></a>;
|
||||||
return <a key={"size"}>{network.format_bytes(size >= 0 ? size : props.file.size, { unit: "B", time: "", exact: false })}</a>;
|
return <a key={"size"}>{network.format_bytes(size >= 0 ? size : props.file.size, { unit: "B", time: "", exact: false })}</a>;
|
||||||
};
|
};
|
||||||
|
@ -439,7 +439,6 @@ const FileTransferIndicator = (props: { file: ListedFileInfo, events: Registry<F
|
||||||
if(event.path !== props.file.path || event.name !== props.file.name)
|
if(event.path !== props.file.path || event.name !== props.file.name)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
console.error(props.file.transfer);
|
|
||||||
setTransferStatus("pending");
|
setTransferStatus("pending");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -456,7 +455,6 @@ const FileTransferIndicator = (props: { file: ListedFileInfo, events: Registry<F
|
||||||
if(event.id !== props.file.transfer?.id)
|
if(event.id !== props.file.transfer?.id)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
console.error("Progress: " + event.progress);
|
|
||||||
setTransferProgress(event.progress);
|
setTransferProgress(event.progress);
|
||||||
setTransferStatus(event.status);
|
setTransferStatus(event.status);
|
||||||
});
|
});
|
||||||
|
@ -609,43 +607,11 @@ const FileListEntry = (props: { row: TableRow<ListedFileInfo>, columns: TableCol
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
setDropHovered(true);
|
setDropHovered(true);
|
||||||
}}
|
}}
|
||||||
onDrop={event => {
|
|
||||||
const types = event.dataTransfer.types;
|
|
||||||
if(types.length !== 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(props.row.userData.type !== FileType.DIRECTORY) {
|
|
||||||
event.stopPropagation();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(types[0] === FileTransferUrlMediaType) {
|
|
||||||
/* TODO: If cross move upload! */
|
|
||||||
console.error(event.dataTransfer.getData(FileTransferUrlMediaType));
|
|
||||||
const fileUrls = event.dataTransfer.getData(FileTransferUrlMediaType).split("&").map(e => decodeURIComponent(e));
|
|
||||||
for(const fileUrl of fileUrls) {
|
|
||||||
const name = fileUrl.split("/").last();
|
|
||||||
const oldPath = fileUrl.split("/").slice(0, -1).join("/") + "/";
|
|
||||||
|
|
||||||
props.events.fire("action_rename_file", {
|
|
||||||
newPath: props.row.userData.path + props.row.userData.name + "/",
|
|
||||||
oldPath: oldPath,
|
|
||||||
oldName: name,
|
|
||||||
newName: name
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if(types[0] === "Files") {
|
|
||||||
props.events.fire("action_start_upload", { path: props.row.userData.path + props.row.userData.name, mode: "files", files: [...event.dataTransfer.files] });
|
|
||||||
} else {
|
|
||||||
log.warn(LogCategory.FILE_TRANSFER, tr("Received an unknown drop media type (%o)"), types);
|
|
||||||
event.preventDefault();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
event.preventDefault();
|
|
||||||
}}
|
|
||||||
|
|
||||||
onDragLeave={() => setDropHovered(false)}
|
onDragLeave={() => setDropHovered(false)}
|
||||||
onDragEnd={() => props.events.fire("notify_drag_ended")}
|
onDragEnd={() => props.events.fire("notify_drag_ended")}
|
||||||
|
|
||||||
|
x-drag-upload-path={props.row.userData.type === FileType.DIRECTORY ? props.row.userData.path + props.row.userData.name + "/" : undefined}
|
||||||
>
|
>
|
||||||
<FileTransferIndicator events={props.events} file={props.row.userData} />
|
<FileTransferIndicator events={props.events} file={props.row.userData} />
|
||||||
</TableRowElement>
|
</TableRowElement>
|
||||||
|
@ -772,6 +738,23 @@ export class FileBrowser extends ReactComponentBase<FileListTableProperties, Fil
|
||||||
|
|
||||||
onHeaderContextMenu={e => this.onHeaderContextMenu(e)}
|
onHeaderContextMenu={e => this.onHeaderContextMenu(e)}
|
||||||
onBodyContextMenu={e => this.onBodyContextMenu(e)}
|
onBodyContextMenu={e => this.onBodyContextMenu(e)}
|
||||||
|
onDrop={e => this.onDrop(e)}
|
||||||
|
onDragOver={event => {
|
||||||
|
const types = event.dataTransfer.types;
|
||||||
|
if(types.length !== 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(types[0] === FileTransferUrlMediaType) {
|
||||||
|
/* TODO: Detect if its remote move or internal move */
|
||||||
|
event.dataTransfer.effectAllowed = "move";
|
||||||
|
} else if(types[0] === "Files") {
|
||||||
|
event.dataTransfer.effectAllowed = "copy";
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
}}
|
||||||
|
|
||||||
renderRow={(row: TableRow<ListedFileInfo>, columns, uniqueId) => <FileListEntry columns={columns} row={row} key={uniqueId} events={this.props.events} />}
|
renderRow={(row: TableRow<ListedFileInfo>, columns, uniqueId) => <FileListEntry columns={columns} row={row} key={uniqueId} events={this.props.events} />}
|
||||||
/>
|
/>
|
||||||
|
@ -786,6 +769,46 @@ export class FileBrowser extends ReactComponentBase<FileListTableProperties, Fil
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onDrop(event: React.DragEvent) {
|
||||||
|
const types = event.dataTransfer.types;
|
||||||
|
if(types.length !== 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
event.stopPropagation();
|
||||||
|
let targetPath;
|
||||||
|
{
|
||||||
|
let currentTarget = event.target as HTMLElement;
|
||||||
|
while(currentTarget && !currentTarget.hasAttribute("x-drag-upload-path"))
|
||||||
|
currentTarget = currentTarget.parentElement;
|
||||||
|
targetPath = currentTarget?.getAttribute("x-drag-upload-path") || this.currentPath;
|
||||||
|
console.log("Target: %o %s", currentTarget, targetPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(types[0] === FileTransferUrlMediaType) {
|
||||||
|
/* TODO: If cross move upload! */
|
||||||
|
console.error(event.dataTransfer.getData(FileTransferUrlMediaType));
|
||||||
|
const fileUrls = event.dataTransfer.getData(FileTransferUrlMediaType).split("&").map(e => decodeURIComponent(e));
|
||||||
|
for(const fileUrl of fileUrls) {
|
||||||
|
const name = fileUrl.split("/").last();
|
||||||
|
const oldPath = fileUrl.split("/").slice(0, -1).join("/") + "/";
|
||||||
|
|
||||||
|
this.props.events.fire("action_rename_file", {
|
||||||
|
newPath: targetPath,
|
||||||
|
oldPath: oldPath,
|
||||||
|
oldName: name,
|
||||||
|
newName: name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if(types[0] === "Files") {
|
||||||
|
this.props.events.fire("action_start_upload", { path: targetPath, mode: "files", files: [...event.dataTransfer.files] });
|
||||||
|
} else {
|
||||||
|
log.warn(LogCategory.FILE_TRANSFER, tr("Received an unknown drop media type (%o)"), types);
|
||||||
|
event.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
private onHeaderContextMenu(event: React.MouseEvent) {
|
private onHeaderContextMenu(event: React.MouseEvent) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
|
@ -1038,7 +1061,7 @@ export class FileBrowser extends ReactComponentBase<FileListTableProperties, Fil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
element.transfer.status = event.status;
|
element.transfer.status = event.status;
|
||||||
if(element.mode === "uploading") {
|
if(element.mode === "uploading" && event.status === "finished") {
|
||||||
/* upload finished, the element rerenders already with the correct values */
|
/* upload finished, the element rerenders already with the correct values */
|
||||||
element.size = event.fileSize;
|
element.size = event.fileSize;
|
||||||
element.mode = "normal";
|
element.mode = "normal";
|
||||||
|
|
|
@ -4,10 +4,27 @@
|
||||||
.container {
|
.container {
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
padding-bottom: 4em; /* for the transfer info */
|
padding-bottom: 4em; /* for the transfer info */
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
flex-shrink: 1;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
width: 90em;
|
||||||
|
min-width: 10em;
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
|
height: 55em;
|
||||||
|
max-height: 100%;
|
||||||
|
min-height: 10em;
|
||||||
|
|
||||||
.navigation {
|
.navigation {
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
.containerIcon {
|
.containerIcon {
|
||||||
margin: auto .25em;
|
margin: auto .25em;
|
||||||
padding: .2em;
|
padding: .2em;
|
||||||
|
@ -79,11 +96,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.fileTable {
|
.fileTable {
|
||||||
min-height: 5em;
|
min-height: 5em;
|
||||||
max-height: 40em;
|
|
||||||
height: 400px;
|
flex-grow: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
|
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
|
|
||||||
|
|
|
@ -212,7 +212,7 @@ class FileTransferModal extends Modal {
|
||||||
|
|
||||||
renderBody() {
|
renderBody() {
|
||||||
const path = this.defaultChannelId ? "/" + channelPathPrefix + this.defaultChannelId + "/" : "/";
|
const path = this.defaultChannelId ? "/" + channelPathPrefix + this.defaultChannelId + "/" : "/";
|
||||||
return <div className={cssStyle.container} style={{width: "600px"}}>
|
return <div className={cssStyle.container}>
|
||||||
<NavigationBar events={this.remoteBrowseEvents} currentPath={path} />
|
<NavigationBar events={this.remoteBrowseEvents} currentPath={path} />
|
||||||
<FileBrowser events={this.remoteBrowseEvents} currentPath={path} />
|
<FileBrowser events={this.remoteBrowseEvents} currentPath={path} />
|
||||||
<TransferInfo events={this.transferInfoEvents} />
|
<TransferInfo events={this.transferInfoEvents} />
|
||||||
|
|
|
@ -10,14 +10,23 @@ import * as ppt from "tc-backend/ppt";
|
||||||
import {SpecialKey} from "tc-shared/PPTListener";
|
import {SpecialKey} from "tc-shared/PPTListener";
|
||||||
import {spawnYesNo} from "tc-shared/ui/modal/ModalYesNo";
|
import {spawnYesNo} from "tc-shared/ui/modal/ModalYesNo";
|
||||||
import {tra, traj} from "tc-shared/i18n/localize";
|
import {tra, traj} from "tc-shared/i18n/localize";
|
||||||
import {FileTransfer, FileTransferState, FileUploadTransfer, TransferProvider} from "tc-shared/file/Transfer";
|
import {
|
||||||
|
FileTransfer,
|
||||||
|
FileTransferState,
|
||||||
|
FileUploadTransfer,
|
||||||
|
TransferProvider,
|
||||||
|
TransferTargetType
|
||||||
|
} from "tc-shared/file/Transfer";
|
||||||
import {createErrorModal} from "tc-shared/ui/elements/Modal";
|
import {createErrorModal} from "tc-shared/ui/elements/Modal";
|
||||||
import {
|
import {
|
||||||
avatarsPathPrefix,
|
avatarsPathPrefix,
|
||||||
channelPathPrefix,
|
channelPathPrefix,
|
||||||
FileBrowserEvents,
|
FileBrowserEvents,
|
||||||
iconPathPrefix, ListedFileInfo, PathInfo
|
iconPathPrefix,
|
||||||
|
ListedFileInfo,
|
||||||
|
PathInfo
|
||||||
} from "tc-shared/ui/modal/transfer/ModalFileTransfer";
|
} from "tc-shared/ui/modal/transfer/ModalFileTransfer";
|
||||||
|
import {Settings, settings} from "tc-shared/settings";
|
||||||
|
|
||||||
function parsePath(path: string, connection: ConnectionHandler) : PathInfo {
|
function parsePath(path: string, connection: ConnectionHandler) : PathInfo {
|
||||||
if(path === "/" || !path) {
|
if(path === "/" || !path) {
|
||||||
|
@ -649,6 +658,17 @@ export function initializeRemoteFileBrowserController(connection: ConnectionHand
|
||||||
events.on("action_start_download", event => {
|
events.on("action_start_download", event => {
|
||||||
event.files.forEach(file => {
|
event.files.forEach(file => {
|
||||||
try {
|
try {
|
||||||
|
let targetSupplier;
|
||||||
|
if(__build.target === "client" && TransferProvider.provider().targetSupported(TransferTargetType.FILE)) {
|
||||||
|
const target = TransferProvider.provider().createFileTarget(undefined, file.name);
|
||||||
|
targetSupplier = async () => target;
|
||||||
|
} else if(TransferProvider.provider().targetSupported(TransferTargetType.DOWNLOAD)) {
|
||||||
|
targetSupplier = async () => await TransferProvider.provider().createDownloadTarget();
|
||||||
|
} else {
|
||||||
|
createErrorModal(tr("Failed to create transfer target"), tr("Failed to create transfer target.\nAll targets are unsupported")).open();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const fileName = file.name;
|
const fileName = file.name;
|
||||||
const info = parsePath(file.path, connection);
|
const info = parsePath(file.path, connection);
|
||||||
const transfer = connection.fileManager.initializeFileDownload({
|
const transfer = connection.fileManager.initializeFileDownload({
|
||||||
|
@ -656,7 +676,7 @@ export function initializeRemoteFileBrowserController(connection: ConnectionHand
|
||||||
path: info.type === "channel" ? info.path : "",
|
path: info.type === "channel" ? info.path : "",
|
||||||
name: info.type === "channel" ? file.name : "/" + file.name,
|
name: info.type === "channel" ? file.name : "/" + file.name,
|
||||||
channelPassword: info.channel?.cached_password(),
|
channelPassword: info.channel?.cached_password(),
|
||||||
targetSupplier: async () => TransferProvider.provider().createDownloadTarget()
|
targetSupplier: targetSupplier
|
||||||
});
|
});
|
||||||
transfer.awaitFinished().then(() => {
|
transfer.awaitFinished().then(() => {
|
||||||
if(transfer.transferState() === FileTransferState.ERRORED) {
|
if(transfer.transferState() === FileTransferState.ERRORED) {
|
||||||
|
@ -736,12 +756,12 @@ export function initializeRemoteFileBrowserController(connection: ConnectionHand
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileTransferState.RUNNING:
|
case FileTransferState.RUNNING:
|
||||||
events.fire("notify_transfer_status", { id: transfer.clientTransferId, status: "transferring", fileSize: transfer.transferProperties().fileSize });
|
events.fire("notify_transfer_status", { id: transfer.clientTransferId, status: "transferring" });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileTransferState.FINISHED:
|
case FileTransferState.FINISHED:
|
||||||
case FileTransferState.CANCELED:
|
case FileTransferState.CANCELED:
|
||||||
events.fire("notify_transfer_status", { id: transfer.clientTransferId, status: "finished" });
|
events.fire("notify_transfer_status", { id: transfer.clientTransferId, status: "finished", fileSize: transfer.transferProperties().fileSize });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileTransferState.ERRORED:
|
case FileTransferState.ERRORED:
|
||||||
|
|
|
@ -135,7 +135,8 @@
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
|
||||||
display: block;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,8 @@ export interface TableProperties {
|
||||||
|
|
||||||
onHeaderContextMenu?: (event: React.MouseEvent) => void;
|
onHeaderContextMenu?: (event: React.MouseEvent) => void;
|
||||||
onBodyContextMenu?: (event: React.MouseEvent) => void;
|
onBodyContextMenu?: (event: React.MouseEvent) => void;
|
||||||
|
onDrop?: (event: React.DragEvent) => void;
|
||||||
|
onDragOver?: (event: React.DragEvent) => void;
|
||||||
|
|
||||||
renderRow?: (row: TableRow, columns: TableColumn[], uniqueId: string) => React.ReactElement<TableRowElement>;
|
renderRow?: (row: TableRow, columns: TableColumn[], uniqueId: string) => React.ReactElement<TableRowElement>;
|
||||||
}
|
}
|
||||||
|
@ -140,7 +142,10 @@ export class Table extends React.Component<TableProperties, TableState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cssStyle.container + " " + (this.props.className || " ")}>
|
<div
|
||||||
|
className={cssStyle.container + " " + (this.props.className || " ")}
|
||||||
|
onDrop={e => this.props.onDrop && this.props.onDrop(e)}
|
||||||
|
onDragOver={e => this.props.onDragOver && this.props.onDragOver(e)}>
|
||||||
<div
|
<div
|
||||||
ref={this.refHeader}
|
ref={this.refHeader}
|
||||||
className={cssStyle.header + " " + (this.props.headerClassName || " ")}
|
className={cssStyle.header + " " + (this.props.headerClassName || " ")}
|
||||||
|
|
|
@ -19,7 +19,7 @@ debugger;
|
||||||
debugger;
|
debugger;
|
||||||
const zzz = true ? "yyy" : "bbb";
|
const zzz = true ? "yyy" : "bbb";
|
||||||
|
|
||||||
const y = "";
|
const zy = "";
|
||||||
debugger;
|
debugger;
|
||||||
debugger;
|
debugger;
|
||||||
debugger;
|
debugger;
|
||||||
|
|
|
@ -60,16 +60,15 @@ TransferProvider.setProvider(new class extends TransferProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
executeFileDownload(transfer: FileDownloadTransfer) {
|
executeFileDownload(transfer: FileDownloadTransfer) {
|
||||||
transfer.targetSupplier(transfer).then(target => {
|
try {
|
||||||
if(!target) throw tr("transfer target is undefined");
|
if(!transfer.target) throw tr("transfer target is undefined");
|
||||||
transfer.target = target;
|
|
||||||
|
|
||||||
let response: Promise<void>;
|
let response: Promise<void>;
|
||||||
transfer.setTransferState(FileTransferState.CONNECTING);
|
transfer.setTransferState(FileTransferState.CONNECTING);
|
||||||
if(target instanceof ResponseTransferTargetImpl) {
|
if(transfer.target instanceof ResponseTransferTargetImpl) {
|
||||||
response = responseFileDownload(transfer, target);
|
response = responseFileDownload(transfer, transfer.target);
|
||||||
} else if(target instanceof DownloadTransferTargetImpl) {
|
} else if(transfer.target instanceof DownloadTransferTargetImpl) {
|
||||||
response = downloadFileDownload(transfer, target);
|
response = downloadFileDownload(transfer, transfer.target);
|
||||||
} else {
|
} else {
|
||||||
transfer.setFailed({
|
transfer.setFailed({
|
||||||
error: "io",
|
error: "io",
|
||||||
|
@ -93,7 +92,7 @@ TransferProvider.setProvider(new class extends TransferProvider {
|
||||||
extraMessage: typeof error === "string" ? error : tr("Lookup the console")
|
extraMessage: typeof error === "string" ? error : tr("Lookup the console")
|
||||||
}, typeof error === "string" ? error : tr("Lookup the console"));
|
}, typeof error === "string" ? error : tr("Lookup the console"));
|
||||||
});
|
});
|
||||||
}).catch(error => {
|
} catch (error) {
|
||||||
if(typeof error !== "string")
|
if(typeof error !== "string")
|
||||||
log.error(LogCategory.FILE_TRANSFER, tr("Failed to initialize transfer target: %o"), error);
|
log.error(LogCategory.FILE_TRANSFER, tr("Failed to initialize transfer target: %o"), error);
|
||||||
|
|
||||||
|
@ -102,7 +101,7 @@ TransferProvider.setProvider(new class extends TransferProvider {
|
||||||
reason: "failed-to-initialize-target",
|
reason: "failed-to-initialize-target",
|
||||||
extraMessage: typeof error === "string" ? error : tr("Lookup the console")
|
extraMessage: typeof error === "string" ? error : tr("Lookup the console")
|
||||||
}, typeof error === "string" ? error : tr("Lookup the console"));
|
}, typeof error === "string" ? error : tr("Lookup the console"));
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
targetSupported(type: TransferTargetType) {
|
targetSupported(type: TransferTargetType) {
|
||||||
|
|
Loading…
Reference in New Issue