Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(app): support editor preference #18932

Merged
merged 32 commits into from
Nov 18, 2021
Merged
Changes from 4 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f7ed56f
editors
lmiller1990 Nov 16, 2021
6049388
update openerId to binary
lmiller1990 Nov 16, 2021
b2087f8
types
lmiller1990 Nov 16, 2021
cd71378
work- around
lmiller1990 Nov 16, 2021
e35ca7d
refactor
lmiller1990 Nov 16, 2021
fc75a08
wip
lmiller1990 Nov 16, 2021
98f8972
rejig actions
lmiller1990 Nov 16, 2021
c9fa9e8
update gql fragments on front-end
lmiller1990 Nov 16, 2021
d986400
update test
lmiller1990 Nov 16, 2021
b3d1be2
remove old code
lmiller1990 Nov 16, 2021
2b39a25
lint
lmiller1990 Nov 16, 2021
a46ad68
remove old test
lmiller1990 Nov 16, 2021
064132e
merge in origin
lmiller1990 Nov 17, 2021
749ac79
wip
lmiller1990 Nov 17, 2021
b1597bd
use i18n
lmiller1990 Nov 17, 2021
19effdb
use live mutation
lmiller1990 Nov 17, 2021
431b361
save editor in same format as other preferences
lmiller1990 Nov 17, 2021
97deed7
update editor opening api
lmiller1990 Nov 17, 2021
53bba38
wip: types
lmiller1990 Nov 17, 2021
d237e0b
types
lmiller1990 Nov 17, 2021
599e15a
lint
lmiller1990 Nov 17, 2021
bb5005f
types
lmiller1990 Nov 17, 2021
5eb6244
simplify types
lmiller1990 Nov 17, 2021
28cf9b4
implement prox ysettings
lmiller1990 Nov 17, 2021
c99a9d4
types
lmiller1990 Nov 17, 2021
b4a42ef
old code
lmiller1990 Nov 17, 2021
bc0fd71
old import
lmiller1990 Nov 17, 2021
2171f98
update test code
lmiller1990 Nov 17, 2021
c9597bb
remove old code
lmiller1990 Nov 17, 2021
7d0cfbf
merge in origin
lmiller1990 Nov 17, 2021
7af5a52
allow using custom editor
lmiller1990 Nov 18, 2021
026aa34
add tests
lmiller1990 Nov 18, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/app/src/settings/SettingsContainer.vue
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@
:icon="IconLaptop"
max-height="800px"
>
<ExternalEditorSettings :gql="props.gql" />
<DeviceSettings />
</SettingsCard>
<SettingsCard
@@ -42,6 +43,7 @@
import { useI18n } from '@cy/i18n'
import { gql, useMutation } from '@urql/vue'
import Button from '@cy/components/Button.vue'
import ExternalEditorSettings from './device/ExternalEditorSettings.vue'
import SettingsCard from './SettingsCard.vue'
import ProjectSettings from './project/ProjectSettings.vue'
import DeviceSettings from './device/DeviceSettings.vue'
@@ -64,6 +66,7 @@ fragment SettingsContainer on Query {
id
...ProjectSettings
}
...ExternalEditorSettings
}`

const props = defineProps<{
2 changes: 0 additions & 2 deletions packages/app/src/settings/device/DeviceSettings.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
<template>
<ExternalEditorSettings />
<TestingPreferences />
<ProxySettings />
</template>

<script lang="ts" setup>
import ExternalEditorSettings from './ExternalEditorSettings.vue'
import ProxySettings from './ProxySettings.vue'
import TestingPreferences from './TestingPreferences.vue'
</script>
113 changes: 73 additions & 40 deletions packages/app/src/settings/device/ExternalEditorSettings.vue
Original file line number Diff line number Diff line change
@@ -7,25 +7,27 @@
{{ t('settingsPage.editor.description') }}
</template>
<Select
v-model="selectedEditor"
:model-value="selectedEditor"
:options="externalEditors"
item-value="name"
item-key="id"
:placeholder="t('settingsPage.editor.noEditorSelectedPlaceholder')"
class="w-300px"
@update:model-value="updateEditor"
>
<template #input-prefix="{ value }">
<Icon
v-if="value"
:icon="value.icon"
:icon="icons[value.id]"
class="text-md"
/>
<Icon
v-else
:icon="IconTerminal"
n="IconTerminal"
class="text-gray-600 text-md"
/>
</template>
<template #item-prefix="{value}">
<template #item-prefix="{ value }">
<Icon
:icon="value.icon"
class="text-md"
@@ -36,8 +38,7 @@
</template>

<script lang="ts" setup>

import { ref } from 'vue'
import { computed, FunctionalComponent, ref, SVGAttributes, watchEffect } from 'vue'
import Icon from '@cy/components/Icon.vue'
import SettingsSection from '../SettingsSection.vue'
import { useI18n } from '@cy/i18n'
@@ -49,41 +50,73 @@ import Vim from '~icons/logos/vim'
import Sublime from '~icons/logos/sublimetext-icon'
import Emacs from '~icons/logos/emacs'
import IconTerminal from '~icons/mdi/terminal'
import { gql } from '@urql/core'
import type { ExternalEditorSettingsFragment } from '../../generated/graphql'
import type { EditorId } from '@packages/types/src/editors'
import { useMutation } from '@urql/vue'
import { SetPreferredEditorDocument } from '@packages/data-context/src/gen/all-operations.gen'

interface EditorItem {
name: string
key: string
binary: string | null
icon: FunctionalComponent<SVGAttributes, {}>
}

// @ts-ignore (lachlan): add all icons for all editors
const icons: Record<EditorId, EditorItem['icon']> = {
'code': VSCode,
'webstorm': Webstorm,
'atom': Atom,
'sublimetext': Sublime,
'sublimetext2': Sublime,
'sublimetextdev': Sublime,
'vim': Vim,
'emacs': Emacs,
}

const externalEditors = computed(() => {
return props.gql.editors.map((x) => ({ ...x, icon: icons[x.id] }))
})

gql`
mutation SetPreferredEditor ($binary: String!) {
setPreferredEditor (binary: $binary)
}`

gql`
fragment ExternalEditorSettings on Query {
editors {
id
name
binary
isPreferred
}
}`

// TODO, grab these from gql or the user's machine.
const externalEditors = [
{
name: 'Visual Studio Code',
key: 'vscode',
icon: VSCode,
},
{
name: 'Webstorm',
key: 'webstorm',
icon: Webstorm,
},
{
name: 'Atom',
key: 'atom',
icon: Atom,
},
{
name: 'Sublime Text',
key: 'sublime',
icon: Sublime,
},
{
name: 'Vim',
key: 'vim',
icon: Vim,
},
{
name: 'Emacs',
key: 'emacs',
icon: Emacs,
},
]
const setPreferredEditor = useMutation(SetPreferredEditorDocument)

const props = defineProps<{
gql: ExternalEditorSettingsFragment
}>()

type ExternalEditor = ExternalEditorSettingsFragment['editors'][number]

const { t } = useI18n()
const selectedEditor = ref<Record<string, any>>()
const selectedEditor = ref<ExternalEditor | undefined>(undefined)

const updateEditor = async (editor: ExternalEditor) => {
if (!editor?.binary) {
return
}

await setPreferredEditor.executeMutation({ binary: editor.binary })
selectedEditor.value = editor
}

watchEffect(() => {
const preferred = props.gql.editors.find((x) => x.isPreferred)

selectedEditor.value = preferred
})
</script>
6 changes: 6 additions & 0 deletions packages/data-context/src/DataActions.ts
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ import type { DataContext } from '.'
import { AppActions, ElectronActions, FileActions, ProjectActions, WizardActions } from './actions'
import { AuthActions } from './actions/AuthActions'
import { DevActions } from './actions/DevActions'
import { EditorActions } from './actions/EditorActions'
import { cached } from './util'

export class DataActions {
@@ -41,4 +42,9 @@ export class DataActions {
get electron () {
return new ElectronActions(this.ctx)
}

@cached
get editor () {
return new EditorActions(this.ctx)
}
}
13 changes: 13 additions & 0 deletions packages/data-context/src/DataContext.ts
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@ import {
CloudDataSource,
ConfigDataSource,
EnvDataSource,
EditorDataSource,
GraphQLDataSource,
HtmlDataSource,
UtilDataSource,
@@ -30,6 +31,7 @@ import type { AddressInfo } from 'net'
import EventEmitter from 'events'
import type { App as ElectronApp } from 'electron'
import { VersionsDataSource } from './sources/VersionsDataSource'
import type { EditorApiShape } from './actions/EditorActions'

const IS_DEV_ENV = process.env.CYPRESS_INTERNAL_ENV !== 'production'

@@ -54,6 +56,7 @@ export interface DataContextConfig {
authApi: AuthApiShape
projectApi: ProjectApiShape
electronApi: ElectronApiShape
editorApi: EditorApiShape
/**
* Internal options used for testing purposes
*/
@@ -80,6 +83,10 @@ export class DataContext {
return this._config.electronApi
}

get editorApi () {
return this._config.editorApi
}

get isGlobalMode () {
return !this.currentProject
}
@@ -162,6 +169,11 @@ export class DataContext {
return new FileDataSource(this)
}

@cached
get editor () {
return new EditorDataSource(this)
}

@cached
get git () {
return new GitDataSource(this)
@@ -287,6 +299,7 @@ export class DataContext {
authApi: this._config.authApi,
projectApi: this._config.projectApi,
electronApi: this._config.electronApi,
editorApi: this._config.editorApi,
busApi: this._rootBus,
}
}
19 changes: 19 additions & 0 deletions packages/data-context/src/actions/EditorActions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { DataContext } from '..'
import type { Editor, EditorsResult } from '@packages/types'

export interface EditorApiShape {
getAllEditors (): Promise<EditorsResult>
setPreferredEditor (editor: Editor): Promise<void>
}

export class EditorActions {
constructor (private ctx: DataContext) { }

getAllEditors () {
return this.ctx.editorApi.getAllEditors()
}

async setPreferredEditor (editor: Editor) {
return this.ctx.editorApi.setPreferredEditor(editor)
}
}
1 change: 1 addition & 0 deletions packages/data-context/src/actions/index.ts
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@ export * from './AppActions'
export * from './AuthActions'
export * from './DataEmitterActions'
export * from './DevActions'
export * from './EditorActions'
export * from './ElectronActions'
export * from './FileActions'
export * from './ProjectActions'
10 changes: 9 additions & 1 deletion packages/data-context/src/data/coreDataShape.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BUNDLERS, FoundBrowser, FoundSpec, FullConfig, Preferences } from '@packages/types'
import type { NexusGenEnums, TestingTypeEnum } from '@packages/graphql/src/gen/nxs.gen'
import type { NexusGenEnums, NexusGenObjects, TestingTypeEnum } from '@packages/graphql/src/gen/nxs.gen'
import type { BrowserWindow } from 'electron'
import type { ChildProcess } from 'child_process'

@@ -19,6 +19,10 @@ export interface DevStateShape {
refreshState: null | string
}

export interface EditorDataShape {
all: NexusGenObjects['Editor'][]
}

export interface ConfigChildProcessShape {
process: ChildProcess
executedPlugins: null | 'e2e' | 'ct'
@@ -70,6 +74,7 @@ export interface BaseErrorDataShape {
export interface CoreDataShape {
baseError: BaseErrorDataShape | null
dev: DevStateShape
editor: EditorDataShape
app: AppDataShape
currentProject: ActiveProjectShape | null
wizard: WizardDataShape
@@ -93,6 +98,9 @@ export function makeCoreData (): CoreDataShape {
browsers: null,
projects: [],
},
editor: {
all: [],
},
isAuthBrowserOpened: false,
currentProject: null,
wizard: {
9 changes: 9 additions & 0 deletions packages/data-context/src/sources/EditorDataSource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { DataContext } from '..'

export class EditorDataSource {
constructor (private ctx: DataContext) {}

async getEditors (): Promise<any> {
return this.ctx._apis.editorApi.getAllEditors()
}
}
1 change: 1 addition & 0 deletions packages/data-context/src/sources/index.ts
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
export * from './BrowserDataSource'
export * from './CloudDataSource'
export * from './ConfigDataSource'
export * from './EditorDataSource'
export * from './EnvDataSource'
export * from './FileDataSource'
export * from './GitDataSource'
10 changes: 5 additions & 5 deletions packages/desktop-gui/cypress/integration/settings_spec.js
Original file line number Diff line number Diff line change
@@ -782,11 +782,11 @@ describe('Settings', () => {

describe('file preference panel', () => {
const availableEditors = [
{ id: 'atom', name: 'Atom', isOther: false, openerId: 'atom' },
{ id: 'vim', name: 'Vim', isOther: false, openerId: 'vim' },
{ id: 'sublime', name: 'Sublime Text', isOther: false, openerId: 'sublime' },
{ id: 'vscode', name: 'Visual Studio Code', isOther: false, openerId: 'vscode' },
{ id: 'other', name: 'Other', isOther: true, openerId: '' },
{ id: 'atom', name: 'Atom', isOther: false, binary: 'atom' },
{ id: 'vim', name: 'Vim', isOther: false, binary: 'vim' },
{ id: 'sublime', name: 'Sublime Text', isOther: false, binary: 'sublime' },
{ id: 'vscode', name: 'Visual Studio Code', isOther: false, binary: 'vscode' },
{ id: 'other', name: 'Other', isOther: true, binary: '' },
]

beforeEach(function () {
12 changes: 6 additions & 6 deletions packages/desktop-gui/cypress/integration/specs_list_spec.js
Original file line number Diff line number Diff line change
@@ -904,12 +904,12 @@ describe('Specs List', function () {
describe('opens files', function () {
beforeEach(function () {
this.availableEditors = [
{ id: 'computer', name: 'On Computer', isOther: false, openerId: 'computer' },
{ id: 'atom', name: 'Atom', isOther: false, openerId: 'atom' },
{ id: 'vim', name: 'Vim', isOther: false, openerId: 'vim' },
{ id: 'sublime', name: 'Sublime Text', isOther: false, openerId: 'sublime' },
{ id: 'vscode', name: 'Visual Studio Code', isOther: false, openerId: 'vscode' },
{ id: 'other', name: 'Other', isOther: true, openerId: '' },
{ id: 'computer', name: 'On Computer', isOther: false, binary: 'computer' },
{ id: 'atom', name: 'Atom', isOther: false, binary: 'atom' },
{ id: 'vim', name: 'Vim', isOther: false, binary: 'vim' },
{ id: 'sublime', name: 'Sublime Text', isOther: false, binary: 'sublime' },
{ id: 'vscode', name: 'Visual Studio Code', isOther: false, binary: 'vscode' },
{ id: 'other', name: 'Other', isOther: true, binary: '' },
]

cy.get('@spec').realHover()
2 changes: 1 addition & 1 deletion packages/desktop-gui/src/settings/file-preference.jsx
Original file line number Diff line number Diff line change
@@ -39,7 +39,7 @@ const FilePreference = observer(() => {
setOtherPath: action((otherPath) => {
const otherOption = _.find(state.editors, { isOther: true })

otherOption.openerId = otherPath
otherOption.binary = otherPath
save(otherOption)
}),
}))
Loading