@@ -16,6 +16,7 @@ import { s3FileViewerHelpUrl } from '../shared/constants'
16
16
import { FileProvider , VirualFileSystem } from '../shared/virtualFilesystem'
17
17
import { PromptSettings } from '../shared/settings'
18
18
import { telemetry } from '../shared/telemetry/telemetry'
19
+ import { ToolkitError } from '../shared/errors'
19
20
20
21
export const S3_EDIT_SCHEME = 's3'
21
22
export const S3_READ_SCHEME = 's3-readonly'
@@ -54,8 +55,9 @@ export class S3FileProvider implements FileProvider {
54
55
const stats = await this . client . headObject ( { bucketName : bucket . name , key } )
55
56
56
57
this . updateETag ( stats . ETag )
57
- this . _file . sizeBytes = stats . ContentLength
58
+ this . _file . sizeBytes = stats . ContentLength ?? this . _file . sizeBytes
58
59
this . _file . lastModified = stats . LastModified
60
+ this . _file . ContentType = stats . ContentType
59
61
}
60
62
61
63
public async read ( ) : Promise < Uint8Array > {
@@ -88,12 +90,13 @@ export class S3FileProvider implements FileProvider {
88
90
return telemetry . s3_uploadObject . run ( async span => {
89
91
span . record ( { component : 'viewer' } )
90
92
93
+ const mimeType = mime . contentType ( path . extname ( this . _file . name ) ) || undefined
91
94
const result = await this . client
92
95
. uploadFile ( {
93
96
content,
94
97
key : this . _file . key ,
95
98
bucketName : this . _file . bucket . name ,
96
- contentType : mime . contentType ( path . extname ( this . _file . name ) ) || undefined ,
99
+ contentType : this . _file . ContentType ?? mimeType ,
97
100
} )
98
101
. then ( u => u . promise ( ) )
99
102
@@ -123,8 +126,7 @@ export class S3FileViewerManager {
123
126
private readonly fs : VirualFileSystem ,
124
127
private readonly window : typeof vscode . window = vscode . window ,
125
128
private readonly settings = PromptSettings . instance ,
126
- private readonly commands : typeof vscode . commands = vscode . commands ,
127
- private readonly workspace : typeof vscode . workspace = vscode . workspace
129
+ private readonly schemes = { read : S3_READ_SCHEME , edit : S3_EDIT_SCHEME }
128
130
) {
129
131
this . disposables . push ( this . registerTabCleanup ( ) )
130
132
}
@@ -141,7 +143,7 @@ export class S3FileViewerManager {
141
143
}
142
144
143
145
private registerTabCleanup ( ) : vscode . Disposable {
144
- return this . workspace . onDidCloseTextDocument ( async doc => {
146
+ return vscode . workspace . onDidCloseTextDocument ( async doc => {
145
147
const key = this . fs . uriToKey ( doc . uri )
146
148
await this . activeTabs [ key ] ?. dispose ( )
147
149
} )
@@ -155,26 +157,29 @@ export class S3FileViewerManager {
155
157
options ?: vscode . TextDocumentShowOptions
156
158
) : Promise < vscode . TextEditor | undefined > {
157
159
const fsPath = fileUri . fsPath
158
-
159
160
await this . activeTabs [ this . fs . uriToKey ( fileUri ) ] ?. dispose ( )
160
161
161
- // Defer to `vscode.open` for non-text files
162
- const contentType = mime . contentType ( path . extname ( fsPath ) )
163
- if ( contentType && mime . charset ( contentType ) != 'UTF-8' ) {
164
- await this . commands . executeCommand ( 'vscode.open' , fileUri )
165
- return this . window . visibleTextEditors . find (
166
- e => this . fs . uriToKey ( e . document . uri ) === this . fs . uriToKey ( fileUri )
167
- )
168
- }
162
+ try {
163
+ // Defer to `vscode.open` for non-text files
164
+ const contentType = mime . contentType ( path . extname ( fsPath ) )
165
+ if ( ! contentType || mime . charset ( contentType ) !== 'UTF-8' ) {
166
+ await vscode . commands . executeCommand ( 'vscode.open' , fileUri )
167
+ return this . window . visibleTextEditors . find (
168
+ e => this . fs . uriToKey ( e . document . uri ) === this . fs . uriToKey ( fileUri )
169
+ )
170
+ }
169
171
170
- const document = await this . workspace . openTextDocument ( fileUri )
171
- return await this . window . showTextDocument ( document , options )
172
+ const document = await vscode . workspace . openTextDocument ( fileUri )
173
+ return await this . window . showTextDocument ( document , options )
174
+ } catch ( err ) {
175
+ throw ToolkitError . chain ( err , 'Failed to open document' , { code : 'FailedToOpen' } )
176
+ }
172
177
}
173
178
174
179
private async closeEditor ( editor : vscode . TextEditor | undefined ) : Promise < void > {
175
180
if ( editor && ! editor . document . isClosed ) {
176
181
await this . window . showTextDocument ( editor . document , { preserveFocus : false } )
177
- await this . commands . executeCommand ( 'workbench.action.closeActiveEditor' )
182
+ await vscode . commands . executeCommand ( 'workbench.action.closeActiveEditor' )
178
183
}
179
184
}
180
185
@@ -192,7 +197,7 @@ export class S3FileViewerManager {
192
197
await this . window . showTextDocument ( activeTab . editor . document )
193
198
} else {
194
199
getLogger ( ) . verbose ( `S3FileViewer: Reopening non-text document` )
195
- await this . commands . executeCommand ( 'vscode.open' , uri )
200
+ await vscode . commands . executeCommand ( 'vscode.open' , uri )
196
201
}
197
202
198
203
return activeTab
@@ -209,8 +214,8 @@ export class S3FileViewerManager {
209
214
const contentType = mime . contentType ( path . extname ( file . name ) )
210
215
const isTextDocument = contentType && mime . charset ( contentType ) == 'UTF-8'
211
216
212
- const uri = S3FileViewerManager . fileToUri ( file , TabMode . Read )
213
- if ( await this . tryFocusTab ( uri , uri . with ( { scheme : S3_EDIT_SCHEME } ) ) ) {
217
+ const uri = this . fileToUri ( file , TabMode . Read )
218
+ if ( await this . tryFocusTab ( uri , uri . with ( { scheme : this . schemes . edit } ) ) ) {
214
219
return
215
220
}
216
221
@@ -224,13 +229,13 @@ export class S3FileViewerManager {
224
229
225
230
/**
226
231
* Opens the tab in edit mode with the use of an S3Tab, or shifts focus to an edit tab if any.
227
- * Exiting read-only tabs are closed as they cannot be converted to edit tabs.
232
+ * Existing read-only tabs are closed as they cannot be converted to edit tabs.
228
233
*
229
234
* @param uriOrFile to be opened
230
235
*/
231
236
public async openInEditMode ( uriOrFile : vscode . Uri | S3File ) : Promise < void > {
232
- const uri = uriOrFile instanceof vscode . Uri ? uriOrFile : S3FileViewerManager . fileToUri ( uriOrFile , TabMode . Edit )
233
- const activeTab = await this . tryFocusTab ( uri , uri . with ( { scheme : S3_READ_SCHEME } ) )
237
+ const uri = uriOrFile instanceof vscode . Uri ? uriOrFile : this . fileToUri ( uriOrFile , TabMode . Edit )
238
+ const activeTab = await this . tryFocusTab ( uri , uri . with ( { scheme : this . schemes . read } ) )
234
239
const file = activeTab ?. file ?? uriOrFile
235
240
236
241
if ( activeTab ?. mode === TabMode . Edit ) {
@@ -254,7 +259,7 @@ export class S3FileViewerManager {
254
259
this . fs . registerProvider ( uri , provider ) ,
255
260
provider . onDidChange ( ( ) => {
256
261
// TODO: find the correct node instead of refreshing it all
257
- this . commands . executeCommand ( 'aws.refreshAwsExplorer' , true )
262
+ vscode . commands . executeCommand ( 'aws.refreshAwsExplorer' , true )
258
263
} )
259
264
)
260
265
}
@@ -267,7 +272,7 @@ export class S3FileViewerManager {
267
272
throw new CancellationError ( 'user' )
268
273
}
269
274
270
- const uri = S3FileViewerManager . fileToUri ( file , mode )
275
+ const uri = this . fileToUri ( file , mode )
271
276
const key = this . fs . uriToKey ( uri )
272
277
const provider = ( this . providers [ key ] ??= this . registerProvider ( file , uri ) )
273
278
const editor = await this . openEditor ( uri , { preview : mode === TabMode . Read } )
@@ -353,8 +358,8 @@ export class S3FileViewerManager {
353
358
} )
354
359
}
355
360
356
- private static fileToUri ( file : S3File , mode : TabMode ) : vscode . Uri {
357
- const scheme = mode === TabMode . Read ? S3_READ_SCHEME : S3_EDIT_SCHEME
361
+ private fileToUri ( file : S3File , mode : TabMode ) : vscode . Uri {
362
+ const scheme = mode === TabMode . Read ? this . schemes . read : this . schemes . edit
358
363
359
364
return vscode . Uri . parse ( `${ scheme } :` , true ) . with ( {
360
365
path : [ '' , file . bucket . region , file . bucket . name , file . key ] . join ( '/' ) ,
0 commit comments