@theia/filesystem 1.65.0-next.55 → 1.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/download/file-download-command-contribution.d.ts +1 -1
- package/lib/browser/download/file-download-command-contribution.d.ts.map +1 -1
- package/lib/browser/download/file-download-command-contribution.js +3 -3
- package/lib/browser/download/file-download-command-contribution.js.map +1 -1
- package/lib/browser/download/file-download-frontend-module.d.ts.map +1 -1
- package/lib/browser/download/file-download-frontend-module.js +2 -1
- package/lib/browser/download/file-download-frontend-module.js.map +1 -1
- package/lib/browser/download/file-download-service.d.ts +2 -10
- package/lib/browser/download/file-download-service.d.ts.map +1 -1
- package/lib/browser/download/file-download-service.js +8 -7
- package/lib/browser/download/file-download-service.js.map +1 -1
- package/lib/browser/file-tree/file-tree-widget.d.ts +1 -1
- package/lib/browser/file-tree/file-tree-widget.d.ts.map +1 -1
- package/lib/browser/file-tree/file-tree-widget.js +3 -3
- package/lib/browser/file-tree/file-tree-widget.js.map +1 -1
- package/lib/browser/filesystem-frontend-contribution.d.ts +2 -2
- package/lib/browser/filesystem-frontend-contribution.d.ts.map +1 -1
- package/lib/browser/filesystem-frontend-contribution.js +3 -3
- package/lib/browser/filesystem-frontend-contribution.js.map +1 -1
- package/lib/browser/filesystem-frontend-module.d.ts.map +1 -1
- package/lib/browser/filesystem-frontend-module.js +3 -2
- package/lib/browser/filesystem-frontend-module.js.map +1 -1
- package/lib/browser/{file-upload-service.d.ts → upload/file-upload-service-impl.d.ts} +16 -52
- package/lib/browser/upload/file-upload-service-impl.d.ts.map +1 -0
- package/lib/browser/{file-upload-service.js → upload/file-upload-service-impl.js} +27 -27
- package/lib/browser/upload/file-upload-service-impl.js.map +1 -0
- package/lib/browser-only/browser-only-filesystem-frontend-module.d.ts.map +1 -1
- package/lib/browser-only/browser-only-filesystem-frontend-module.js +8 -0
- package/lib/browser-only/browser-only-filesystem-frontend-module.js.map +1 -1
- package/lib/browser-only/download/file-download-command-contribution.d.ts +15 -0
- package/lib/browser-only/download/file-download-command-contribution.d.ts.map +1 -0
- package/lib/browser-only/download/file-download-command-contribution.js +55 -0
- package/lib/browser-only/download/file-download-command-contribution.js.map +1 -0
- package/lib/browser-only/download/file-download-frontend-module.d.ts +4 -0
- package/lib/browser-only/download/file-download-frontend-module.d.ts.map +1 -0
- package/lib/browser-only/download/file-download-frontend-module.js +27 -0
- package/lib/browser-only/download/file-download-frontend-module.js.map +1 -0
- package/lib/browser-only/download/file-download-service.d.ts +86 -0
- package/lib/browser-only/download/file-download-service.d.ts.map +1 -0
- package/lib/browser-only/download/file-download-service.js +551 -0
- package/lib/browser-only/download/file-download-service.js.map +1 -0
- package/lib/browser-only/file-search.d.ts +38 -0
- package/lib/browser-only/file-search.d.ts.map +1 -0
- package/lib/browser-only/file-search.js +153 -0
- package/lib/browser-only/file-search.js.map +1 -0
- package/lib/browser-only/opfs-filesystem-initialization.d.ts +4 -2
- package/lib/browser-only/opfs-filesystem-initialization.d.ts.map +1 -1
- package/lib/browser-only/opfs-filesystem-initialization.js +4 -1
- package/lib/browser-only/opfs-filesystem-initialization.js.map +1 -1
- package/lib/browser-only/opfs-filesystem-provider.d.ts +89 -12
- package/lib/browser-only/opfs-filesystem-provider.d.ts.map +1 -1
- package/lib/browser-only/opfs-filesystem-provider.js +345 -181
- package/lib/browser-only/opfs-filesystem-provider.js.map +1 -1
- package/lib/browser-only/upload/file-upload-service-impl.d.ts +67 -0
- package/lib/browser-only/upload/file-upload-service-impl.d.ts.map +1 -0
- package/lib/browser-only/upload/file-upload-service-impl.js +328 -0
- package/lib/browser-only/upload/file-upload-service-impl.js.map +1 -0
- package/lib/common/download/file-download.d.ts +17 -0
- package/lib/common/download/file-download.d.ts.map +1 -0
- package/lib/common/download/{file-download-data.js → file-download.js} +3 -2
- package/lib/common/download/file-download.js.map +1 -0
- package/lib/common/files.d.ts +8 -1
- package/lib/common/files.d.ts.map +1 -1
- package/lib/common/files.js +35 -1
- package/lib/common/files.js.map +1 -1
- package/lib/common/io.js +7 -1
- package/lib/common/io.js.map +1 -1
- package/lib/common/upload/file-upload.d.ts +45 -0
- package/lib/common/upload/file-upload.d.ts.map +1 -0
- package/{src/common/download/file-download-data.ts → lib/common/upload/file-upload.js} +6 -13
- package/lib/common/upload/file-upload.js.map +1 -0
- package/lib/node/disk-file-system-provider.d.ts.map +1 -1
- package/lib/node/disk-file-system-provider.js +2 -4
- package/lib/node/disk-file-system-provider.js.map +1 -1
- package/lib/node/download/file-download-handler.js +2 -2
- package/lib/node/download/file-download-handler.js.map +1 -1
- package/lib/node/filesystem-backend-module.js +1 -1
- package/lib/node/filesystem-backend-module.js.map +1 -1
- package/lib/node/parcel-watcher/parcel-filesystem-service.d.ts +2 -2
- package/lib/node/parcel-watcher/parcel-filesystem-service.d.ts.map +1 -1
- package/lib/node/parcel-watcher/parcel-filesystem-service.js.map +1 -1
- package/lib/node/upload/node-file-upload-service.d.ts.map +1 -0
- package/lib/node/{node-file-upload-service.js → upload/node-file-upload-service.js} +1 -1
- package/lib/node/upload/node-file-upload-service.js.map +1 -0
- package/package.json +10 -5
- package/src/browser/download/file-download-command-contribution.ts +1 -1
- package/src/browser/download/file-download-frontend-module.ts +3 -2
- package/src/browser/download/file-download-service.ts +7 -12
- package/src/browser/file-tree/file-tree-widget.tsx +1 -1
- package/src/browser/filesystem-frontend-contribution.ts +2 -2
- package/src/browser/filesystem-frontend-module.ts +3 -2
- package/src/browser/{file-upload-service.ts → upload/file-upload-service-impl.ts} +31 -72
- package/src/browser-only/browser-only-filesystem-frontend-module.ts +10 -0
- package/src/browser-only/download/file-download-command-contribution.ts +56 -0
- package/src/browser-only/download/file-download-frontend-module.ts +26 -0
- package/src/browser-only/download/file-download-service.ts +726 -0
- package/src/browser-only/file-search.ts +170 -0
- package/src/browser-only/opfs-filesystem-initialization.ts +7 -4
- package/src/browser-only/opfs-filesystem-provider.ts +402 -189
- package/src/browser-only/upload/file-upload-service-impl.ts +408 -0
- package/src/common/download/file-download.ts +40 -0
- package/src/common/files.ts +42 -1
- package/src/common/io.ts +6 -1
- package/src/common/upload/file-upload.ts +65 -0
- package/src/node/disk-file-system-provider.ts +3 -4
- package/src/node/download/file-download-handler.ts +1 -1
- package/src/node/filesystem-backend-module.ts +1 -1
- package/src/node/parcel-watcher/parcel-filesystem-service.ts +2 -2
- package/src/node/{node-file-upload-service.ts → upload/node-file-upload-service.ts} +1 -1
- package/lib/browser/file-upload-service.d.ts.map +0 -1
- package/lib/browser/file-upload-service.js.map +0 -1
- package/lib/common/download/file-download-data.d.ts +0 -7
- package/lib/common/download/file-download-data.d.ts.map +0 -1
- package/lib/common/download/file-download-data.js.map +0 -1
- package/lib/node/node-file-upload-service.d.ts.map +0 -1
- package/lib/node/node-file-upload-service.js.map +0 -1
- /package/lib/node/{node-file-upload-service.d.ts → upload/node-file-upload-service.d.ts} +0 -0
package/package.json
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theia/filesystem",
|
|
3
|
-
"version": "1.65.0
|
|
3
|
+
"version": "1.65.0",
|
|
4
4
|
"description": "Theia - FileSystem Extension",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@theia/core": "1.65.0
|
|
6
|
+
"@theia/core": "1.65.0",
|
|
7
7
|
"@types/body-parser": "^1.17.0",
|
|
8
8
|
"@types/multer": "^1.4.7",
|
|
9
9
|
"@types/tar-fs": "^1.16.1",
|
|
10
|
+
"@types/tar-stream": "^3.1.4",
|
|
10
11
|
"async-mutex": "^0.3.1",
|
|
11
12
|
"body-parser": "^1.18.3",
|
|
12
13
|
"http-status-codes": "^1.3.0",
|
|
13
|
-
"
|
|
14
|
+
"ignore": "^6.0.0",
|
|
15
|
+
"minimatch": "^10.0.3",
|
|
14
16
|
"multer": "^2.0.1",
|
|
17
|
+
"opfs-worker": "1.3.1",
|
|
15
18
|
"rimraf": "^5.0.0",
|
|
16
19
|
"stat-mode": "^1.0.0",
|
|
17
20
|
"tar-fs": "^3.0.9",
|
|
21
|
+
"tar-stream": "^3.1.7",
|
|
18
22
|
"trash": "^7.2.0",
|
|
19
23
|
"tslib": "^2.6.2",
|
|
20
24
|
"vscode-languageserver-textdocument": "^1.0.1"
|
|
@@ -37,6 +41,7 @@
|
|
|
37
41
|
},
|
|
38
42
|
{
|
|
39
43
|
"frontend": "lib/browser/download/file-download-frontend-module",
|
|
44
|
+
"frontendOnly": "lib/browser-only/download/file-download-frontend-module",
|
|
40
45
|
"backend": "lib/node/download/file-download-backend-module"
|
|
41
46
|
},
|
|
42
47
|
{
|
|
@@ -72,10 +77,10 @@
|
|
|
72
77
|
"watch": "theiaext watch"
|
|
73
78
|
},
|
|
74
79
|
"devDependencies": {
|
|
75
|
-
"@theia/ext-scripts": "1.
|
|
80
|
+
"@theia/ext-scripts": "1.65.0"
|
|
76
81
|
},
|
|
77
82
|
"nyc": {
|
|
78
83
|
"extends": "../../configs/nyc.json"
|
|
79
84
|
},
|
|
80
|
-
"gitHead": "
|
|
85
|
+
"gitHead": "500dfc80cee94fd2a623b5fb59b22d5a575247c2"
|
|
81
86
|
}
|
|
@@ -21,7 +21,7 @@ import { environment } from '@theia/core/shared/@theia/application-package/lib/e
|
|
|
21
21
|
import { SelectionService } from '@theia/core/lib/common/selection-service';
|
|
22
22
|
import { Command, CommandContribution, CommandRegistry } from '@theia/core/lib/common/command';
|
|
23
23
|
import { UriAwareCommandHandler } from '@theia/core/lib/common/uri-command-handler';
|
|
24
|
-
import { FileDownloadService } from '
|
|
24
|
+
import { FileDownloadService } from '../../common/download/file-download';
|
|
25
25
|
import { CommonCommands } from '@theia/core/lib/browser';
|
|
26
26
|
|
|
27
27
|
@injectable()
|
|
@@ -16,10 +16,11 @@
|
|
|
16
16
|
|
|
17
17
|
import { ContainerModule } from '@theia/core/shared/inversify';
|
|
18
18
|
import { CommandContribution } from '@theia/core/lib/common/command';
|
|
19
|
-
import { FileDownloadService } from '
|
|
19
|
+
import { FileDownloadService } from '../../common/download/file-download';
|
|
20
|
+
import { FileDownloadServiceImpl } from './file-download-service';
|
|
20
21
|
import { FileDownloadCommandContribution } from './file-download-command-contribution';
|
|
21
22
|
|
|
22
23
|
export default new ContainerModule(bind => {
|
|
23
|
-
bind(FileDownloadService).
|
|
24
|
+
bind(FileDownloadService).to(FileDownloadServiceImpl).inSingletonScope();
|
|
24
25
|
bind(CommandContribution).to(FileDownloadCommandContribution).inSingletonScope();
|
|
25
26
|
});
|
|
@@ -14,22 +14,23 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
17
|
+
import { inject, injectable, named } from '@theia/core/shared/inversify';
|
|
18
18
|
import URI from '@theia/core/lib/common/uri';
|
|
19
19
|
import { ILogger } from '@theia/core/lib/common/logger';
|
|
20
20
|
import { Endpoint } from '@theia/core/lib/browser/endpoint';
|
|
21
|
-
import { FileDownloadData } from '../../common/download/file-download-data';
|
|
22
21
|
import { MessageService } from '@theia/core/lib/common/message-service';
|
|
23
22
|
import { addClipboardListener } from '@theia/core/lib/browser/widgets';
|
|
24
23
|
import { nls } from '@theia/core';
|
|
24
|
+
import type { FileDownloadData, FileDownloadService } from '../../common/download/file-download';
|
|
25
25
|
|
|
26
26
|
@injectable()
|
|
27
|
-
export class FileDownloadService {
|
|
27
|
+
export class FileDownloadServiceImpl implements FileDownloadService {
|
|
28
28
|
|
|
29
29
|
protected anchor: HTMLAnchorElement | undefined;
|
|
30
30
|
protected downloadCounter: number = 0;
|
|
31
31
|
|
|
32
32
|
@inject(ILogger)
|
|
33
|
+
@named('file-download')
|
|
33
34
|
protected readonly logger: ILogger;
|
|
34
35
|
|
|
35
36
|
@inject(MessageService)
|
|
@@ -49,10 +50,13 @@ export class FileDownloadService {
|
|
|
49
50
|
|
|
50
51
|
async download(uris: URI[], options?: FileDownloadService.DownloadOptions): Promise<void> {
|
|
51
52
|
let cancel = false;
|
|
53
|
+
|
|
52
54
|
if (uris.length === 0) {
|
|
53
55
|
return;
|
|
54
56
|
}
|
|
57
|
+
|
|
55
58
|
const copyLink = options && options.copyLink ? true : false;
|
|
59
|
+
|
|
56
60
|
try {
|
|
57
61
|
const text: string = copyLink ?
|
|
58
62
|
nls.localize('theia/filesystem/prepareDownloadLink', 'Preparing download link...') :
|
|
@@ -168,12 +172,3 @@ export class FileDownloadService {
|
|
|
168
172
|
}
|
|
169
173
|
|
|
170
174
|
}
|
|
171
|
-
|
|
172
|
-
export namespace FileDownloadService {
|
|
173
|
-
export interface DownloadOptions {
|
|
174
|
-
/**
|
|
175
|
-
* `true` if the download link has to be copied to the clipboard. This will not trigger the actual download. Defaults to `false`.
|
|
176
|
-
*/
|
|
177
|
-
readonly copyLink?: boolean;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
@@ -21,13 +21,13 @@ import URI from '@theia/core/lib/common/uri';
|
|
|
21
21
|
import { UriSelection } from '@theia/core/lib/common/selection';
|
|
22
22
|
import { isCancelled } from '@theia/core/lib/common/cancellation';
|
|
23
23
|
import { ContextMenuRenderer, NodeProps, TreeProps, TreeNode, CompositeTreeNode, CompressedTreeWidget, CompressedNodeProps } from '@theia/core/lib/browser';
|
|
24
|
-
import { FileUploadService } from '../file-upload-service';
|
|
25
24
|
import { DirNode, FileStatNode, FileStatNodeData } from './file-tree';
|
|
26
25
|
import { FileTreeModel } from './file-tree-model';
|
|
27
26
|
import { IconThemeService } from '@theia/core/lib/browser/icon-theme-service';
|
|
28
27
|
import { ApplicationShell } from '@theia/core/lib/browser/shell';
|
|
29
28
|
import { FileStat, FileType } from '../../common/files';
|
|
30
29
|
import { isOSX } from '@theia/core';
|
|
30
|
+
import { FileUploadService } from '../../common/upload/file-upload';
|
|
31
31
|
|
|
32
32
|
export const FILE_TREE_CLASS = 'theia-FileTree';
|
|
33
33
|
export const FILE_STAT_NODE_CLASS = 'theia-FileStatNode';
|
|
@@ -41,8 +41,8 @@ import { FileChangeType, FileChangesEvent, FileOperation } from '../common/files
|
|
|
41
41
|
import { FileDialogService, SaveFileDialogProps } from './file-dialog';
|
|
42
42
|
import { FileSelection } from './file-selection';
|
|
43
43
|
import { FileService, UserFileOperationEvent } from './file-service';
|
|
44
|
-
import { FileUploadResult, FileUploadService } from './file-upload-service';
|
|
45
44
|
import { FileSystemPreferences } from '../common/filesystem-preferences';
|
|
45
|
+
import { FileUploadService } from '../common/upload/file-upload';
|
|
46
46
|
|
|
47
47
|
export namespace FileSystemCommands {
|
|
48
48
|
|
|
@@ -161,7 +161,7 @@ export class FileSystemFrontendContribution implements FrontendApplicationContri
|
|
|
161
161
|
});
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
protected async upload(selection: FileSelection): Promise<
|
|
164
|
+
protected async upload(selection: FileSelection): Promise<FileUploadService.UploadResult | undefined> {
|
|
165
165
|
try {
|
|
166
166
|
const source = TreeWidgetSelection.getSource(this.selectionService.selection);
|
|
167
167
|
const fileUploadResult = await this.uploadService.upload(selection.fileStat.isDirectory ? selection.fileStat.resource : selection.fileStat.resource.parent);
|
|
@@ -22,7 +22,6 @@ import { WebSocketConnectionProvider, FrontendApplicationContribution, LabelProv
|
|
|
22
22
|
import { FileResourceResolver } from './file-resource';
|
|
23
23
|
import { bindFileSystemPreferences } from '../common/filesystem-preferences';
|
|
24
24
|
import { FileSystemFrontendContribution } from './filesystem-frontend-contribution';
|
|
25
|
-
import { FileUploadService } from './file-upload-service';
|
|
26
25
|
import { FileTreeDecoratorAdapter, FileTreeLabelProvider } from './file-tree';
|
|
27
26
|
import { FileService, FileServiceContribution } from './file-service';
|
|
28
27
|
import { RemoteFileSystemProvider, RemoteFileSystemServer, remoteFileSystemPath, RemoteFileSystemProxyFactory } from '../common/remote-file-system-provider';
|
|
@@ -34,6 +33,8 @@ import { BreadcrumbsFileTreeWidget, createFileTreeBreadcrumbsWidget } from './br
|
|
|
34
33
|
import { FilesystemSaveableService } from './filesystem-saveable-service';
|
|
35
34
|
import { SaveableService } from '@theia/core/lib/browser/saveable-service';
|
|
36
35
|
import { VSCodeFileServiceContribution, VSCodeFileSystemProvider } from './vscode-file-service-contribution';
|
|
36
|
+
import { FileUploadService } from '../common/upload/file-upload';
|
|
37
|
+
import { FileUploadServiceImpl } from './upload/file-upload-service-impl';
|
|
37
38
|
|
|
38
39
|
export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
39
40
|
bindFileSystemPreferences(bind);
|
|
@@ -55,7 +56,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
|
55
56
|
|
|
56
57
|
bindFileResource(bind);
|
|
57
58
|
|
|
58
|
-
bind(FileUploadService).
|
|
59
|
+
bind(FileUploadService).to(FileUploadServiceImpl).inSingletonScope();
|
|
59
60
|
|
|
60
61
|
bind(FileSystemFrontendContribution).toSelf().inSingletonScope();
|
|
61
62
|
bind(CommandContribution).toService(FileSystemFrontendContribution);
|
|
@@ -24,41 +24,27 @@ import { MessageService } from '@theia/core/lib/common/message-service';
|
|
|
24
24
|
import { Progress } from '@theia/core/lib/common/message-service-protocol';
|
|
25
25
|
import { Endpoint } from '@theia/core/lib/browser/endpoint';
|
|
26
26
|
import throttle = require('@theia/core/shared/lodash.throttle');
|
|
27
|
-
import { HTTP_FILE_UPLOAD_PATH } from '
|
|
27
|
+
import { HTTP_FILE_UPLOAD_PATH } from '../../common/file-upload';
|
|
28
28
|
import { Semaphore } from 'async-mutex';
|
|
29
|
-
import { FileSystemPreferences } from '
|
|
30
|
-
import { FileService } from '
|
|
29
|
+
import { FileSystemPreferences } from '../../common/filesystem-preferences';
|
|
30
|
+
import { FileService } from '../file-service';
|
|
31
31
|
import { ConfirmDialog, Dialog } from '@theia/core/lib/browser';
|
|
32
32
|
import { nls } from '@theia/core/lib/common/nls';
|
|
33
33
|
import { Emitter, Event } from '@theia/core/lib/common/event';
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
readonly name: string;
|
|
43
|
-
data(): Promise<Uint8Array>;
|
|
44
|
-
} | undefined
|
|
45
|
-
}
|
|
46
|
-
export interface FileUploadParams {
|
|
47
|
-
source?: DataTransfer | CustomDataTransfer
|
|
48
|
-
progress?: FileUploadProgressParams
|
|
49
|
-
onDidUpload?: (uri: string) => void;
|
|
50
|
-
leaveInTemp?: boolean // dont move file out of the initial tmp directory
|
|
51
|
-
}
|
|
52
|
-
export interface FileUploadProgressParams {
|
|
53
|
-
text: string
|
|
34
|
+
import type { CustomDataTransfer, FileUploadService } from '../../common/upload/file-upload';
|
|
35
|
+
|
|
36
|
+
interface UploadFilesParams {
|
|
37
|
+
source: FileUploadService.Source,
|
|
38
|
+
progress: Progress,
|
|
39
|
+
token: CancellationToken,
|
|
40
|
+
leaveInTemp?: boolean,
|
|
41
|
+
onDidUpload?: (uri: string) => void,
|
|
54
42
|
}
|
|
55
43
|
|
|
56
|
-
export
|
|
57
|
-
uploaded: string[]
|
|
58
|
-
}
|
|
44
|
+
export const HTTP_UPLOAD_URL: string = new Endpoint({ path: HTTP_FILE_UPLOAD_PATH }).getRestUrl().toString(true);
|
|
59
45
|
|
|
60
46
|
@injectable()
|
|
61
|
-
export class FileUploadService {
|
|
47
|
+
export class FileUploadServiceImpl implements FileUploadService {
|
|
62
48
|
|
|
63
49
|
static TARGET = 'target';
|
|
64
50
|
static UPLOAD = 'upload';
|
|
@@ -70,7 +56,7 @@ export class FileUploadService {
|
|
|
70
56
|
}
|
|
71
57
|
|
|
72
58
|
protected uploadForm: FileUploadService.Form;
|
|
73
|
-
protected deferredUpload?: Deferred<
|
|
59
|
+
protected deferredUpload?: Deferred<FileUploadService.UploadResult>;
|
|
74
60
|
|
|
75
61
|
@inject(MessageService)
|
|
76
62
|
protected readonly messageService: MessageService;
|
|
@@ -95,13 +81,13 @@ export class FileUploadService {
|
|
|
95
81
|
const targetInput = document.createElement('input');
|
|
96
82
|
targetInput.type = 'text';
|
|
97
83
|
targetInput.spellcheck = false;
|
|
98
|
-
targetInput.name =
|
|
84
|
+
targetInput.name = FileUploadServiceImpl.TARGET;
|
|
99
85
|
targetInput.classList.add('theia-input');
|
|
100
86
|
|
|
101
87
|
const fileInput = document.createElement('input');
|
|
102
88
|
fileInput.type = 'file';
|
|
103
89
|
fileInput.classList.add('theia-input');
|
|
104
|
-
fileInput.name =
|
|
90
|
+
fileInput.name = FileUploadServiceImpl.UPLOAD;
|
|
105
91
|
fileInput.multiple = true;
|
|
106
92
|
|
|
107
93
|
const form = document.createElement('form');
|
|
@@ -117,34 +103,32 @@ export class FileUploadService {
|
|
|
117
103
|
const source: FileUploadService.Source = new FormData(form);
|
|
118
104
|
// clean up to allow upload to the same folder twice
|
|
119
105
|
fileInput.value = '';
|
|
120
|
-
const targetUri = new URI(<string>source.get(
|
|
106
|
+
const targetUri = new URI(<string>source.get(FileUploadServiceImpl.TARGET));
|
|
121
107
|
const { resolve, reject } = this.deferredUpload;
|
|
122
108
|
this.deferredUpload = undefined;
|
|
123
109
|
const { onDidUpload } = this.uploadForm;
|
|
124
110
|
this.withProgress(
|
|
125
|
-
(progress, token) => this.uploadAll(targetUri, { source, progress, token, onDidUpload })
|
|
126
|
-
this.uploadForm.progress
|
|
111
|
+
(progress, token) => this.uploadAll(targetUri, { source, progress, token, onDidUpload })
|
|
127
112
|
).then(resolve, reject);
|
|
128
113
|
}
|
|
129
114
|
});
|
|
130
115
|
return { targetInput, fileInput };
|
|
131
116
|
}
|
|
132
117
|
|
|
133
|
-
async upload(targetUri: string | URI, params:
|
|
134
|
-
const { source, onDidUpload, leaveInTemp } = params;
|
|
118
|
+
async upload(targetUri: string | URI, params: FileUploadService.UploadParams): Promise<FileUploadService.UploadResult> {
|
|
119
|
+
const { source, onDidUpload, leaveInTemp } = params || {};
|
|
120
|
+
|
|
135
121
|
if (source) {
|
|
136
122
|
return this.withProgress(
|
|
137
123
|
(progress, token) => this.uploadAll(
|
|
138
124
|
typeof targetUri === 'string' ? new URI(targetUri) : targetUri,
|
|
139
125
|
{ source, progress, token, leaveInTemp, onDidUpload }
|
|
140
|
-
)
|
|
141
|
-
params.progress,
|
|
126
|
+
)
|
|
142
127
|
);
|
|
143
128
|
}
|
|
144
|
-
this.deferredUpload = new Deferred<
|
|
129
|
+
this.deferredUpload = new Deferred<FileUploadService.UploadResult>();
|
|
145
130
|
this.uploadForm.targetInput.value = String(targetUri);
|
|
146
131
|
this.uploadForm.fileInput.click();
|
|
147
|
-
this.uploadForm.progress = params.progress;
|
|
148
132
|
this.uploadForm.onDidUpload = params.onDidUpload;
|
|
149
133
|
return this.deferredUpload.promise;
|
|
150
134
|
}
|
|
@@ -153,14 +137,14 @@ export class FileUploadService {
|
|
|
153
137
|
return HTTP_UPLOAD_URL;
|
|
154
138
|
}
|
|
155
139
|
|
|
156
|
-
protected async uploadAll(targetUri: URI, params:
|
|
140
|
+
protected async uploadAll(targetUri: URI, params: UploadFilesParams): Promise<FileUploadService.UploadResult> {
|
|
157
141
|
const responses: Promise<void>[] = [];
|
|
158
142
|
const status = new Map<File, {
|
|
159
143
|
total: number
|
|
160
144
|
done: number
|
|
161
145
|
uploaded?: boolean
|
|
162
146
|
}>();
|
|
163
|
-
const result:
|
|
147
|
+
const result: FileUploadService.UploadResult = {
|
|
164
148
|
uploaded: []
|
|
165
149
|
};
|
|
166
150
|
/**
|
|
@@ -351,7 +335,7 @@ export class FileUploadService {
|
|
|
351
335
|
resolve();
|
|
352
336
|
} else if (xhr.status === 500 && xhr.statusText !== xhr.response) {
|
|
353
337
|
// internal error with cause message
|
|
354
|
-
// see packages/filesystem/src/node/node-file-upload-service.ts
|
|
338
|
+
// see packages/filesystem/src/node/upload/node-file-upload-service.ts
|
|
355
339
|
reject(new Error(`Internal server error: ${xhr.response}`));
|
|
356
340
|
} else {
|
|
357
341
|
reject(new Error(`POST request failed: ${xhr.status} ${xhr.statusText}`));
|
|
@@ -387,11 +371,11 @@ export class FileUploadService {
|
|
|
387
371
|
}
|
|
388
372
|
|
|
389
373
|
protected async withProgress<T>(
|
|
390
|
-
cb: (progress: Progress, token: CancellationToken) => Promise<T
|
|
391
|
-
{ text }: FileUploadProgressParams = { text: nls.localize('theia/filesystem/uploadFiles', 'Uploading Files') }
|
|
374
|
+
cb: (progress: Progress, token: CancellationToken) => Promise<T>
|
|
392
375
|
): Promise<T> {
|
|
393
376
|
const cancellationSource = new CancellationTokenSource();
|
|
394
377
|
const { token } = cancellationSource;
|
|
378
|
+
const text = nls.localize('theia/filesystem/uploadFiles', 'Uploading Files');
|
|
395
379
|
const progress = await this.messageService.showProgress(
|
|
396
380
|
{ text, options: { cancelable: true } },
|
|
397
381
|
() => cancellationSource.cancel()
|
|
@@ -414,7 +398,7 @@ export class FileUploadService {
|
|
|
414
398
|
}
|
|
415
399
|
|
|
416
400
|
protected async indexFormData(targetUri: URI, formData: FormData, context: FileUploadService.Context): Promise<void> {
|
|
417
|
-
for (const entry of formData.getAll(
|
|
401
|
+
for (const entry of formData.getAll(FileUploadServiceImpl.UPLOAD)) {
|
|
418
402
|
if (entry instanceof File) {
|
|
419
403
|
await this.indexFile(targetUri, entry, context);
|
|
420
404
|
}
|
|
@@ -433,8 +417,9 @@ export class FileUploadService {
|
|
|
433
417
|
protected async indexCustomDataTransfer(targetUri: URI, dataTransfer: CustomDataTransfer, context: FileUploadService.Context): Promise<void> {
|
|
434
418
|
for (const [_, item] of dataTransfer) {
|
|
435
419
|
const fileInfo = item.asFile();
|
|
420
|
+
|
|
436
421
|
if (fileInfo) {
|
|
437
|
-
await this.indexFile(targetUri, new File([await fileInfo.data()], fileInfo.id), context);
|
|
422
|
+
await this.indexFile(targetUri, new File([await fileInfo.data() as BlobPart], fileInfo.id), context);
|
|
438
423
|
}
|
|
439
424
|
}
|
|
440
425
|
}
|
|
@@ -524,29 +509,3 @@ export class FileUploadService {
|
|
|
524
509
|
}
|
|
525
510
|
|
|
526
511
|
}
|
|
527
|
-
|
|
528
|
-
export namespace FileUploadService {
|
|
529
|
-
export type Source = FormData | DataTransfer | CustomDataTransfer;
|
|
530
|
-
export interface UploadEntry {
|
|
531
|
-
file: File
|
|
532
|
-
uri: URI
|
|
533
|
-
}
|
|
534
|
-
export interface Context {
|
|
535
|
-
progress: Progress
|
|
536
|
-
token: CancellationToken
|
|
537
|
-
accept: (entry: UploadEntry) => Promise<void>
|
|
538
|
-
}
|
|
539
|
-
export interface Form {
|
|
540
|
-
targetInput: HTMLInputElement
|
|
541
|
-
fileInput: HTMLInputElement
|
|
542
|
-
progress?: FileUploadProgressParams
|
|
543
|
-
onDidUpload?: (uri: string) => void
|
|
544
|
-
}
|
|
545
|
-
export interface UploadParams {
|
|
546
|
-
source: FileUploadService.Source,
|
|
547
|
-
progress: Progress,
|
|
548
|
-
token: CancellationToken,
|
|
549
|
-
onDidUpload?: (uri: string) => void,
|
|
550
|
-
leaveInTemp?: boolean
|
|
551
|
-
}
|
|
552
|
-
}
|
|
@@ -20,16 +20,26 @@ import { OPFSFileSystemProvider } from './opfs-filesystem-provider';
|
|
|
20
20
|
import { RemoteFileSystemProvider, RemoteFileSystemServer } from '../common/remote-file-system-provider';
|
|
21
21
|
import { OPFSInitialization, DefaultOPFSInitialization } from './opfs-filesystem-initialization';
|
|
22
22
|
import { BrowserOnlyFileSystemProviderServer } from './browser-only-filesystem-provider-server';
|
|
23
|
+
import { FileUploadService } from '../common/upload/file-upload';
|
|
24
|
+
import { FileUploadServiceImpl } from './upload/file-upload-service-impl';
|
|
23
25
|
|
|
24
26
|
export default new ContainerModule((bind, _unbind, isBound, rebind) => {
|
|
25
27
|
bind(DefaultOPFSInitialization).toSelf();
|
|
26
28
|
bind(OPFSFileSystemProvider).toSelf();
|
|
27
29
|
bind(OPFSInitialization).toService(DefaultOPFSInitialization);
|
|
30
|
+
|
|
31
|
+
if (isBound(FileUploadService)) {
|
|
32
|
+
rebind(FileUploadService).to(FileUploadServiceImpl).inSingletonScope();
|
|
33
|
+
} else {
|
|
34
|
+
bind(FileUploadService).to(FileUploadServiceImpl).inSingletonScope();
|
|
35
|
+
}
|
|
36
|
+
|
|
28
37
|
if (isBound(FileSystemProvider)) {
|
|
29
38
|
rebind(FileSystemProvider).to(OPFSFileSystemProvider).inSingletonScope();
|
|
30
39
|
} else {
|
|
31
40
|
bind(FileSystemProvider).to(OPFSFileSystemProvider).inSingletonScope();
|
|
32
41
|
}
|
|
42
|
+
|
|
33
43
|
if (isBound(RemoteFileSystemProvider)) {
|
|
34
44
|
rebind(RemoteFileSystemServer).to(BrowserOnlyFileSystemProviderServer).inSingletonScope();
|
|
35
45
|
} else {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2025 Maksim Kachurin and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
18
|
+
import URI from '@theia/core/lib/common/uri';
|
|
19
|
+
import { SelectionService } from '@theia/core/lib/common/selection-service';
|
|
20
|
+
import { CommandContribution, CommandRegistry } from '@theia/core/lib/common/command';
|
|
21
|
+
import { UriAwareCommandHandler } from '@theia/core/lib/common/uri-command-handler';
|
|
22
|
+
import { FileDownloadService } from '../../common/download/file-download';
|
|
23
|
+
import { FileDownloadCommands } from '../../browser/download/file-download-command-contribution';
|
|
24
|
+
|
|
25
|
+
@injectable()
|
|
26
|
+
export class FileDownloadCommandContribution implements CommandContribution {
|
|
27
|
+
|
|
28
|
+
@inject(FileDownloadService)
|
|
29
|
+
protected readonly downloadService: FileDownloadService;
|
|
30
|
+
|
|
31
|
+
@inject(SelectionService)
|
|
32
|
+
protected readonly selectionService: SelectionService;
|
|
33
|
+
|
|
34
|
+
registerCommands(registry: CommandRegistry): void {
|
|
35
|
+
registry.registerCommand(
|
|
36
|
+
FileDownloadCommands.DOWNLOAD,
|
|
37
|
+
UriAwareCommandHandler.MultiSelect(this.selectionService, {
|
|
38
|
+
execute: uris => this.executeDownload(uris),
|
|
39
|
+
isEnabled: uris => this.isDownloadEnabled(uris),
|
|
40
|
+
isVisible: uris => this.isDownloadVisible(uris),
|
|
41
|
+
})
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
protected async executeDownload(uris: URI[], options?: { copyLink?: boolean }): Promise<void> {
|
|
46
|
+
this.downloadService.download(uris, options);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
protected isDownloadEnabled(uris: URI[]): boolean {
|
|
50
|
+
return uris.length > 0 && uris.every(u => u.scheme === 'file');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
protected isDownloadVisible(uris: URI[]): boolean {
|
|
54
|
+
return this.isDownloadEnabled(uris);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2025 Maksim Kachurin and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { ContainerModule } from '@theia/core/shared/inversify';
|
|
18
|
+
import { FileDownloadService } from '../../common/download/file-download';
|
|
19
|
+
import { FileDownloadServiceImpl } from './file-download-service';
|
|
20
|
+
import { CommandContribution } from '@theia/core/lib/common';
|
|
21
|
+
import { FileDownloadCommandContribution } from './file-download-command-contribution';
|
|
22
|
+
|
|
23
|
+
export default new ContainerModule(bind => {
|
|
24
|
+
bind(FileDownloadService).to(FileDownloadServiceImpl).inSingletonScope();
|
|
25
|
+
bind(CommandContribution).to(FileDownloadCommandContribution).inSingletonScope();
|
|
26
|
+
});
|