mirror of
https://github.com/enso-org/enso.git
synced 2024-11-26 08:52:58 +03:00
Consider currently written path when opening file browser (#10076)
We pass the current path as default to show(Open|Save)FileDialog. # Important Notes There is `wrapper` method of Ast, I assumed it is suitable also for Groups.
This commit is contained in:
parent
ca8d715d5a
commit
65737b34f5
1
app/gui2/env.d.ts
vendored
1
app/gui2/env.d.ts
vendored
@ -29,6 +29,7 @@ interface FileBrowserApi {
|
||||
*/
|
||||
readonly openFileBrowser: (
|
||||
kind: 'file' | 'directory' | 'default' | 'filePath',
|
||||
defaultPath?: string,
|
||||
) => Promise<string[] | undefined>
|
||||
}
|
||||
|
||||
|
@ -1766,6 +1766,10 @@ export class Group extends Ast {
|
||||
return this.module.get(this.fields.get('expression')?.node)
|
||||
}
|
||||
|
||||
wrappedExpression(): Ast | undefined {
|
||||
return this.expression
|
||||
}
|
||||
|
||||
*concreteChildren(_verbatim?: boolean): IterableIterator<RawNodeChild> {
|
||||
const { open, expression, close } = getAll(this.fields)
|
||||
if (open) yield open
|
||||
|
@ -8,7 +8,9 @@ import { Score, WidgetInput, defineWidget, widgetProps } from '@/providers/widge
|
||||
import { useGraphStore } from '@/stores/graph'
|
||||
import type { RequiredImport } from '@/stores/graph/imports'
|
||||
import { Ast } from '@/util/ast'
|
||||
import { Pattern } from '@/util/ast/match'
|
||||
import { ArgumentInfoKey } from '@/util/callTree'
|
||||
import { TextLiteral } from 'shared/ast'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps(widgetProps(widgetDefinition))
|
||||
@ -51,8 +53,22 @@ const label = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const FILE_CONSTRUCTOR = FILE_TYPE + '.new'
|
||||
const FILE_SHORT_CONSTRUCTOR = 'File.new'
|
||||
const fileConPattern = Pattern.parse(`${FILE_TYPE}.new __`)
|
||||
const fileShortConPattern = Pattern.parse(`File.new __`)
|
||||
const currentPath = computed(() => {
|
||||
if (typeof props.input.value === 'string') {
|
||||
return props.input.value
|
||||
} else if (props.input.value) {
|
||||
const expression = props.input.value.innerExpression()
|
||||
const match = fileShortConPattern.match(expression) ?? fileConPattern.match(expression)
|
||||
const pathAst =
|
||||
match && match[0] ? expression.module.get(match[0]).innerExpression() : expression
|
||||
if (pathAst instanceof TextLiteral) {
|
||||
return pathAst.rawTextContent
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
})
|
||||
|
||||
function makeValue(edit: Ast.MutableModule, useFileConstructor: boolean, path: string): Ast.Owned {
|
||||
if (useFileConstructor) {
|
||||
@ -63,29 +79,32 @@ function makeValue(edit: Ast.MutableModule, useFileConstructor: boolean, path: s
|
||||
import: 'File',
|
||||
} as RequiredImport
|
||||
const conflicts = graph.addMissingImports(edit, [requiredImport])
|
||||
const constructor = conflicts != null ? FILE_CONSTRUCTOR : FILE_SHORT_CONSTRUCTOR
|
||||
const constructorAst = Ast.PropertyAccess.tryParse(constructor, edit)
|
||||
if (constructorAst == null) {
|
||||
throw new Error(`Failed to parse constructor as AST: ${constructor}`)
|
||||
}
|
||||
return Ast.App.new(edit, constructorAst, undefined, arg)
|
||||
const pattern = conflicts ? fileConPattern : fileShortConPattern
|
||||
return pattern.instantiate(edit, [arg])
|
||||
} else {
|
||||
return Ast.TextLiteral.new(path, edit)
|
||||
}
|
||||
}
|
||||
|
||||
const onClick = async () => {
|
||||
const selected = await window.fileBrowserApi.openFileBrowser(dialogKind.value)
|
||||
if (selected != null && selected[0] != null) {
|
||||
const edit = graph.startEdit()
|
||||
const value = makeValue(edit, insertAsFileConstructor.value, selected[0])
|
||||
props.onUpdate({
|
||||
edit,
|
||||
portUpdate: {
|
||||
value,
|
||||
origin: props.input.portId,
|
||||
},
|
||||
})
|
||||
if (!window.fileBrowserApi) {
|
||||
console.error('File browser not supported!')
|
||||
} else {
|
||||
const selected = await window.fileBrowserApi.openFileBrowser(
|
||||
dialogKind.value,
|
||||
currentPath.value,
|
||||
)
|
||||
if (selected != null && selected[0] != null) {
|
||||
const edit = graph.startEdit()
|
||||
const value = makeValue(edit, insertAsFileConstructor.value, selected[0])
|
||||
props.onUpdate({
|
||||
edit,
|
||||
portUpdate: {
|
||||
value,
|
||||
origin: props.input.portId,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -445,13 +445,18 @@ class App {
|
||||
)
|
||||
electron.ipcMain.handle(
|
||||
ipc.Channel.openFileBrowser,
|
||||
async (_event, kind: 'default' | 'directory' | 'file' | 'filePath') => {
|
||||
logger.log('Request for opening browser for ', kind)
|
||||
async (
|
||||
_event,
|
||||
kind: 'default' | 'directory' | 'file' | 'filePath',
|
||||
defaultPath?: string
|
||||
) => {
|
||||
logger.log('Request for opening browser for ', kind, defaultPath)
|
||||
let retval = null
|
||||
if (kind === 'filePath') {
|
||||
// "Accept", as the file won't be created immediately.
|
||||
const { canceled, filePath } = await electron.dialog.showSaveDialog({
|
||||
buttonLabel: 'Accept',
|
||||
...(defaultPath != null ? { defaultPath } : {}),
|
||||
})
|
||||
if (!canceled) {
|
||||
retval = [filePath]
|
||||
@ -469,6 +474,7 @@ class App {
|
||||
: ['openFile']
|
||||
const { canceled, filePaths } = await electron.dialog.showOpenDialog({
|
||||
properties,
|
||||
...(defaultPath != null ? { defaultPath } : {}),
|
||||
})
|
||||
if (!canceled) {
|
||||
retval = filePaths
|
||||
|
@ -173,8 +173,8 @@ const AUTHENTICATION_API = {
|
||||
electron.contextBridge.exposeInMainWorld(AUTHENTICATION_API_KEY, AUTHENTICATION_API)
|
||||
|
||||
const FILE_BROWSER_API = {
|
||||
openFileBrowser: (kind: 'any' | 'directory' | 'file' | 'filePath') =>
|
||||
electron.ipcRenderer.invoke(ipc.Channel.openFileBrowser, kind),
|
||||
openFileBrowser: (kind: 'any' | 'directory' | 'file' | 'filePath', defaultPath?: string) =>
|
||||
electron.ipcRenderer.invoke(ipc.Channel.openFileBrowser, kind, defaultPath),
|
||||
}
|
||||
electron.contextBridge.exposeInMainWorld(FILE_BROWSER_API_KEY, FILE_BROWSER_API)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user