From 84dcbd8866ce63c90a0f1bf98be9d124d3b7c4b1 Mon Sep 17 00:00:00 2001 From: Tim Mok Date: Mon, 1 Apr 2024 09:19:05 -0400 Subject: [PATCH] Refactoring Use save callback --- .../modalDialogs/savePlotModalDialog.css | 9 ++-- .../modalDialogs/savePlotModalDialog.tsx | 50 +++++-------------- .../browser/positronPlotsService.ts | 22 +++----- 3 files changed, 23 insertions(+), 58 deletions(-) diff --git a/src/vs/workbench/contrib/positronPlots/browser/modalDialogs/savePlotModalDialog.css b/src/vs/workbench/contrib/positronPlots/browser/modalDialogs/savePlotModalDialog.css index 71cc4807987..f0c7fabe429 100644 --- a/src/vs/workbench/contrib/positronPlots/browser/modalDialogs/savePlotModalDialog.css +++ b/src/vs/workbench/contrib/positronPlots/browser/modalDialogs/savePlotModalDialog.css @@ -87,13 +87,10 @@ img.plot-preview { grid-area: preview; } -.plot-save-dialog-action-bar .left, -.plot-save-dialog-action-bar .right { - display: flex; - gap: 10px; - margin-top: 15px; +.plot-save-dialog-action-bar div.ok-cancel-action-bar { + justify-content: end; } -.button.action-bar-button { +.plot-save-dialog-action-bar .button.action-bar-button { padding: 10px; } diff --git a/src/vs/workbench/contrib/positronPlots/browser/modalDialogs/savePlotModalDialog.tsx b/src/vs/workbench/contrib/positronPlots/browser/modalDialogs/savePlotModalDialog.tsx index 5f827c443dd..5a8e1a60ab2 100644 --- a/src/vs/workbench/contrib/positronPlots/browser/modalDialogs/savePlotModalDialog.tsx +++ b/src/vs/workbench/contrib/positronPlots/browser/modalDialogs/savePlotModalDialog.tsx @@ -18,12 +18,8 @@ import { OKCancelActionBar } from 'vs/workbench/browser/positronComponents/posit import { PositronModalDialog } from 'vs/workbench/browser/positronComponents/positronModalDialog/positronModalDialog'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { PositronModalReactRenderer } from 'vs/workbench/browser/positronModalReactRenderer/positronModalReactRenderer'; -import { Schemas } from 'vs/base/common/network'; -import { HTMLFileSystemProvider } from 'vs/platform/files/browser/htmlFileSystemProvider'; -import { IFileService } from 'vs/platform/files/common/files'; -import { decodeBase64 } from 'vs/base/common/buffer'; -interface SavePlotOptions { +export interface SavePlotOptions { uri: string; path: URI; } @@ -55,9 +51,9 @@ export const showSavePlotModalDialog = async ( layoutService: IWorkbenchLayoutService, keybindingService: IKeybindingService, fileDialogService: IFileDialogService, - fileService: IFileService, plotClient: PlotClientInstance, - suggestedPath?: URI + savePlotCallback: (options: SavePlotOptions) => void, + suggestedPath?: URI, ): Promise => { @@ -71,14 +67,7 @@ export const showSavePlotModalDialog = async ( const plotWidth = plotClient.lastRender?.width ?? 100; const plotHeight = plotClient.lastRender?.height ?? 100; - const getPlotUri = (plotData: string) => { - const regex = /^data:.+\/(.+);base64,(.*)$/; - const matches = plotData.match(regex); - if (!matches || matches.length !== 3) { - return null; - } - return matches; - } + renderer.render( { - const htmlFileSystemProvider = fileService.getProvider(Schemas.file) as HTMLFileSystemProvider; - const matches = getPlotUri(options.uri); - - if (!matches) { - return; - } - - const data = matches[2]; - - htmlFileSystemProvider.writeFile(options.path, decodeBase64(data).buffer, { create: true, overwrite: true, unlock: true, atomic: false }) - .then(() => { - }); - }} + savePlotCallback={savePlotCallback} plotClient={plotClient} /> ); @@ -116,8 +92,8 @@ interface SavePlotModalDialogProps { plotWidth: number; plotHeight: number; plotClient: PlotClientInstance; + savePlotCallback: (options: SavePlotOptions) => void; suggestedPath?: URI; - savePlot: (options: SavePlotOptions) => Promise; } const SavePlotModalDialog = (props: SavePlotModalDialogProps) => { @@ -133,9 +109,13 @@ const SavePlotModalDialog = (props: SavePlotModalDialogProps) => { setUri(props.plotClient.lastRender?.uri ?? ''); }, [props.plotClient.lastRender?.uri]); + const validateInput = React.useCallback((): boolean => { + return path.valid && width.valid && height.valid && dpi.valid; + }, [path, width, height, dpi]); + React.useEffect(() => { validateInput(); - }, [width, height, dpi, path]); + }, [validateInput]); const updateWidth = (widthString: string): void => { const newWidth = parseInt(widthString); @@ -157,10 +137,6 @@ const SavePlotModalDialog = (props: SavePlotModalDialogProps) => { setPath({ value: newPath, valid: !!newPath }); }; - const validateInput = (): boolean => { - return path.valid && width.valid && height.valid && dpi.valid; - }; - const browseHandler = async () => { const uri = await props.fileDialogService.showSaveDialog({ title: title, @@ -184,7 +160,7 @@ const SavePlotModalDialog = (props: SavePlotModalDialogProps) => { const plotResult = await generatePreview(); if (plotResult) { - props.savePlot({ uri: plotResult.uri, path: path.value }); + props.savePlotCallback({ uri: plotResult.uri, path: path.value }); } setRendering(false); @@ -274,5 +250,5 @@ const SavePlotModalDialog = (props: SavePlotModalDialogProps) => { - ) + ); }; diff --git a/src/vs/workbench/contrib/positronPlots/browser/positronPlotsService.ts b/src/vs/workbench/contrib/positronPlots/browser/positronPlotsService.ts index 4db10ac412c..9a143cb626d 100644 --- a/src/vs/workbench/contrib/positronPlots/browser/positronPlotsService.ts +++ b/src/vs/workbench/contrib/positronPlots/browser/positronPlotsService.ts @@ -26,7 +26,7 @@ import { IPositronIPyWidgetsService } from 'vs/workbench/services/positronIPyWid import { Schemas } from 'vs/base/common/network'; import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; import { decodeBase64 } from 'vs/base/common/buffer'; -import { showSavePlotModalDialog } from 'vs/workbench/contrib/positronPlots/browser/modalDialogs/savePlotModalDialog'; +import { SavePlotOptions, showSavePlotModalDialog } from 'vs/workbench/contrib/positronPlots/browser/modalDialogs/savePlotModalDialog'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { URI } from 'vs/base/common/uri'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; @@ -688,11 +688,7 @@ export class PositronPlotsService extends Disposable implements IPositronPlotsSe this.showSavePlotDialog(uri); } else if (plot instanceof PlotClientInstance) { // if it's a dynamic plot, present options dialog - showSavePlotModalDialog(this._layoutService, this._keybindingService, this._fileDialogService, this._fileService, plot, suggestedPath).then(result => { - if (result) { - this.savePlotAs(result.uri, result.path); - } - }); + showSavePlotModalDialog(this._layoutService, this._keybindingService, this._fileDialogService, plot, this.savePlotAs, suggestedPath); } else { // if it's a webview plot, do nothing return; @@ -701,9 +697,9 @@ export class PositronPlotsService extends Disposable implements IPositronPlotsSe } } - private savePlotAs(plotData: string, path: URI) { + private savePlotAs = (options: SavePlotOptions) => { const htmlFileSystemProvider = this._fileService.getProvider(Schemas.file) as HTMLFileSystemProvider; - const matches = this.getPlotUri(plotData); + const matches = this.getPlotUri(options.uri); if (!matches) { return; @@ -711,10 +707,10 @@ export class PositronPlotsService extends Disposable implements IPositronPlotsSe const data = matches[2]; - htmlFileSystemProvider.writeFile(path, decodeBase64(data).buffer, { create: true, overwrite: true, unlock: true, atomic: false }) + htmlFileSystemProvider.writeFile(options.path, decodeBase64(data).buffer, { create: true, overwrite: true, unlock: true, atomic: false }) .then(() => { }); - } + }; private getPlotUri(plotData: string) { const regex = /^data:.+\/(.+);base64,(.*)$/; @@ -732,7 +728,6 @@ export class PositronPlotsService extends Disposable implements IPositronPlotsSe return; } - const data = matches[2]; const extension = matches[1]; this._fileDialogService.showSaveDialog({ @@ -746,10 +741,7 @@ export class PositronPlotsService extends Disposable implements IPositronPlotsSe ], }).then(result => { if (result) { - const htmlFileSystemProvider = this._fileService.getProvider(Schemas.file) as HTMLFileSystemProvider; - htmlFileSystemProvider.writeFile(result, decodeBase64(data).buffer, { create: true, overwrite: true, unlock: true, atomic: false }) - .then(() => { - }); + this.savePlotAs({ path: result, uri }); } }); }