Skip to content

Commit

Permalink
fix: bugs again (#924)
Browse files Browse the repository at this point in the history
  • Loading branch information
molinla committed Sep 21, 2024
1 parent c83846d commit 2f30643
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 69 deletions.
12 changes: 6 additions & 6 deletions spx-gui/src/components/editor/code-editor/chat-bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,14 @@ export class ChatBot {
private i18nInputWithAction(input: string, action: ChatAction): string {
switch (action) {
case ChatAction.explain:
return this.i18n.t({ en: 'Explain the code: ', zh: '解释一下这段代码: ' }) + '\n```gop \n' + input + '\n```'
return this.i18n.t({ en: 'Explain the code: ', zh: '解释一下这段代码: ' }) + input
case ChatAction.comment:
return (
this.i18n.t({ en: 'I want to comment the code: ', zh: '我想给这段代码写注释: ' }) + '\n```gop \n' + input + '\n```'
this.i18n.t({ en: 'I want to comment the code: ', zh: '我想给这段代码写注释: ' }) + input
)
case ChatAction.fixCode:
return (
this.i18n.t({ en: 'I want to fix the code: ', zh: '帮我修复这段代码的问题: ' }) + '\n```gop \n' + input + '\n```'
this.i18n.t({ en: 'I want to fix the code: ', zh: '帮我修复这段代码的问题: ' }) + input
)
}
return ''
Expand Down Expand Up @@ -112,7 +112,7 @@ export class Chat {
messages: [],
length: 0,
loading: true,
currentQuestion: "",
currentQuestion: '',
responseError: false
})

Expand Down Expand Up @@ -163,12 +163,12 @@ export class Chat {
this.chatState.length++
this.chatState.loading = false
this.chatState.currentQuestion = msg
if(res.respMessage == "") {
if (res.respMessage == '') {
this.chatState.responseError = true
return false
}
const content = res.respMessage

const questions = res.respQuestions
const assistantMessage: ChatMessage = {
content: content,
Expand Down
2 changes: 2 additions & 0 deletions spx-gui/src/components/editor/code-editor/compiler.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// todo: refactor this into webWorker

import compilerWasmHtml from '@/assets/compiler/index.html?raw'
import compilerWasm from '@/assets/compiler/main.wasm?url'
import compilerWasmExec from '@/assets/wasm_exec.js?url'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type { Definition, TokenUsage } from '@/components/editor/code-editor/com
import {
type CoordinatorState,
definitionStructName2Target,
transformInput2MarkdownCode,
usageType2Icon
} from '@/components/editor/code-editor/coordinators/index'
import type { TokenWithDoc, UsageWithDoc } from '@/components/editor/code-editor/tokens/types'
Expand Down Expand Up @@ -217,21 +218,15 @@ export class HoverProvider {
}),
activeLabel: this.ui.i18n.t({ zh: '在线答疑', en: 'Online Q&A' }),
onActiveLabelClick: () => {
const usageId = usage.id
this.docAbility.getDetailDoc(doc.id).then((detailDoc) => {
const usageDetailDoc = detailDoc.usages.find(
(usage: UsageWithDoc) => usage.id === usageId
)?.doc
if (usageDetailDoc) {
const chat = this.chatBot.startExplainChat(
usage.declaration + '\n' + usageDetailDoc
)
this.ui.invokeAIChatModal(chat)
} else {
const chat = this.chatBot.startExplainChat(usage.declaration)
this.ui.invokeAIChatModal(chat)
}
})
if (usage.doc) {
const chat = this.chatBot.startExplainChat('\n' + usage.doc)
this.ui.invokeAIChatModal(chat)
} else {
const chat = this.chatBot.startExplainChat(
transformInput2MarkdownCode(usage.declaration)
)
this.ui.invokeAIChatModal(chat)
}
}
},
moreActions: [...this.createDocDetailAction(doc, definition)]
Expand Down Expand Up @@ -267,7 +262,7 @@ export class HoverProvider {
icon: Icon.Document,
label: this.ui.i18n.t({ zh: '查看文档', en: 'Document' }),
onClick: () => {
const usageId = definition.usages.shift()?.usageID
const usageId: string | null = definition.usages[0].usageID
if (!usageId)
throw new Error(
'definition usage is empty when search for doc detail. tokenId: ' +
Expand Down
102 changes: 72 additions & 30 deletions spx-gui/src/components/editor/code-editor/coordinators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,54 @@ export class Coordinator {
header: {
icon: usageEffect2Icon(completionItemDoc.effect),
declaration: transferUsageDeclaration(completionItemDoc.declaration)
}
},
recommendAction: {
label: this.ui.i18n.t({
zh: '还有疑惑?场外求助',
en: 'Still in confusion? Ask for help'
}),
activeLabel: this.ui.i18n.t({ zh: '在线答疑', en: 'Online Q&A' }),
onActiveLabelClick: () => {
if (completionItemDoc.doc) {
const chat = this.chatBot.startExplainChat('\n\n' + completionItemDoc.doc)
this.ui.invokeAIChatModal(chat)
} else {
const chat = this.chatBot.startExplainChat(
transformInput2MarkdownCode(completionItemDoc.declaration)
)
this.ui.invokeAIChatModal(chat)
}
}
},
moreActions: [
{
icon: Icon.Document,
label: this.ui.i18n.t({ zh: '查看文档', en: 'Document' }),
onClick: () => {
const usageId = completionItemDoc.id
this.docAbility
.getDetailDoc({
name: completionItem.tokenName,
pkgPath: completionItem.tokenPkg
})
.then((detailDoc) => {
const usageDetailDoc = detailDoc.usages.find(
(usage: UsageWithDoc) => usage.id === usageId
)?.doc
if (usageDetailDoc) return this.ui.invokeDocumentDetail(usageDetailDoc)
console.warn(
'usageDetailDoc not found. tokenId: ' +
JSON.stringify({
name: completionItem.tokenName,
pkgPath: completionItem.tokenPkg
}) +
' usageId: ' +
usageId
)
})
}
}
]
}
}
}
Expand Down Expand Up @@ -255,23 +302,23 @@ export class Coordinator {
icon: Icon.AIAbility,
label: this.ui.i18n.t({ zh: '对这段代码有疑惑', en: 'Suspect this code' }),
action: () => {
const chat = this.chatBot.startExplainChat(ctx.selectContent)
const chat = this.chatBot.startExplainChat(transformInput2MarkdownCode(ctx.selectContent))
this.ui.invokeAIChatModal(chat)
}
},
{
icon: Icon.AIAbility,
label: this.ui.i18n.t({ zh: '这段代码无法正常运行', en: 'This code cannot run properly' }),
action: () => {
const chat = this.chatBot.startFixCodeChat(ctx.selectContent)
const chat = this.chatBot.startFixCodeChat(transformInput2MarkdownCode(ctx.selectContent))
this.ui.invokeAIChatModal(chat)
}
},
{
icon: Icon.AIAbility,
label: this.ui.i18n.t({ zh: '给这段代码添加注释', en: 'Add explanation to this code' }),
action: () => {
const chat = this.chatBot.startCommentChat(ctx.selectContent)
const chat = this.chatBot.startCommentChat(transformInput2MarkdownCode(ctx.selectContent))
this.ui.invokeAIChatModal(chat)
}
}
Expand All @@ -291,9 +338,8 @@ export class Coordinator {
if (ctx.signal.aborted) return []
this.coordinatorState.inlayHints = inlayHints
return inlayHints.flatMap((inlayHint): InlayHintDecoration[] => {
// from compiler has two type of inlay hint, so here use if else to distinguish

if (inlayHint.type === 'play') return []
// todo: this is temp way to show playlistIcon, need a better way to identify
if (inlayHint.name === 'mediaName') {
return [
{
Expand Down Expand Up @@ -488,7 +534,6 @@ async function toolCategory2InputItemCategory(
const docUsages: Array<UsageWithDoc> = tokenWithDoc.usages

const docUsageIdxMap = new Map<string, number>()

// current logic is only show document, not shown all wasm usages.

// collect all usages from document and next get wasm usage to merge it.
Expand Down Expand Up @@ -534,21 +579,15 @@ async function toolCategory2InputItemCategory(
}),
activeLabel: ui.i18n.t({ zh: '在线答疑', en: 'Online Q&A' }),
onActiveLabelClick: () => {
const usageId = usage.id
docAbility.getDetailDoc(token.id).then((detailDoc) => {
const usageDetailDoc = detailDoc.usages.find(
(usage: UsageWithDoc) => usage.id === usageId
)?.doc
if (usageDetailDoc) {
const chat = chatBot.startExplainChat(
usage.declaration + '\n' + usageDetailDoc
)
ui.invokeAIChatModal(chat)
} else {
const chat = chatBot.startExplainChat(usage.declaration)
ui.invokeAIChatModal(chat)
}
})
if (usage.doc) {
const chat = chatBot.startExplainChat('\n\n' + usage.doc)
ui.invokeAIChatModal(chat)
} else {
const chat = chatBot.startExplainChat(
transformInput2MarkdownCode(usage.declaration)
)
ui.invokeAIChatModal(chat)
}
}
},
moreActions: [
Expand All @@ -561,14 +600,13 @@ async function toolCategory2InputItemCategory(
const usageDetailDoc = detailDoc.usages.find(
(usage: UsageWithDoc) => usage.id === usageId
)?.doc
if (!usageDetailDoc)
return console.warn(
'usageDetailDoc not found. tokenId: ' +
JSON.stringify(token.id) +
' usageId: ' +
usageId
)
ui.invokeDocumentDetail(usageDetailDoc)
if (usageDetailDoc) return ui.invokeDocumentDetail(usageDetailDoc)
console.warn(
'usageDetailDoc not found. tokenId: ' +
JSON.stringify(token.id) +
' usageId: ' +
usageId
)
})
}
}
Expand Down Expand Up @@ -631,3 +669,7 @@ export function definitionStructName2Target(structName: string): 'All' | 'Sprite
return 'All'
}
}

export function transformInput2MarkdownCode(input: string) {
return '\n```gop \n' + input + '\n```'
}
2 changes: 1 addition & 1 deletion spx-gui/src/components/editor/code-editor/tokens/spx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ export const xpos: Token = {
effect: 'read',
target: 'Sprite',
declaration: 'func() float64',
sample: '',
sample: '5',
insertText: 'xpos'
}
]
Expand Down
27 changes: 15 additions & 12 deletions spx-gui/src/components/editor/code-editor/ui/EditorSidebar.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { onMounted, onUnmounted, ref, shallowRef, watch } from 'vue'
import { nextTick, onMounted, onUnmounted, ref, shallowRef, watch } from 'vue'
import ToolItem from './ToolItem.vue'
import IconCollapse from './icons/collapse.svg?raw'
import IconOverview from './icons/overview.svg?raw'
Expand Down Expand Up @@ -63,15 +63,17 @@ function handleCategoryClick(index: number) {
props.ui.documentDetailState.visible = false
activeCategoryIndex.value = index
if (categoryTitleElements.value[index] && sidebarContainerElement.value) {
const el = categoryTitleElements.value[index]
const top = el.offsetTop
sidebarContainerElement.value.scrollTo({
top: top,
behavior: 'smooth'
})
isInCategoryClickScrollingState.value = true
}
nextTick(() => {
if (categoryTitleElements.value[index] && sidebarContainerElement.value) {
const el = categoryTitleElements.value[index]
const top = el.offsetTop
sidebarContainerElement.value.scrollTo({
top: top,
behavior: 'smooth'
})
isInCategoryClickScrollingState.value = true
}
})
}
const categoryTitleElements = ref<HTMLElement[]>([])
Expand All @@ -86,6 +88,7 @@ onBeforeUpdate(() => {
})
function handleScroll() {
if (props.ui.documentDetailState.visible) return
if (!(sidebarContainerElement.value && categoryTitleElements.value.length)) return
cancelCategoryClickScrollingState()
const scrollTop = sidebarContainerElement.value.scrollTop
Expand Down Expand Up @@ -166,7 +169,7 @@ onUnmounted(() => {
}"
class="sidebar-container"
>
<section v-if="!ui.documentDetailState.visible" class="tools-wrapper">
<section v-show="!ui.documentDetailState.visible" class="tools-wrapper">
<template v-if="categories.length">
<template v-for="(category, i) in categories" :key="i">
<h4 :ref="(el) => setCategoryTitleRef(el as HTMLElement | null, i)" class="title">
Expand Down Expand Up @@ -201,7 +204,7 @@ onUnmounted(() => {
</div>
</template>
</section>
<section v-else class="document-wrapper">
<section v-show="ui.documentDetailState.visible" class="document-wrapper">
<header class="header">
<span
:ref="(el) => normalizeIconSize(el as Element, 28)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,7 @@ $markdown-code-font-family: 'JetBrains Mono NL', Consolas, 'Courier New', 'Aliba
h4,
h5,
h6 {
margin-top: 24px;
margin-bottom: 16px;
padding-bottom: 0.3em;
font-weight: 600;
line-height: 1.25;
}
Expand Down Expand Up @@ -237,8 +236,12 @@ $markdown-code-font-family: 'JetBrains Mono NL', Consolas, 'Courier New', 'Aliba
background-color: #f6f8fa;
}
& > *:first-child {
margin-top: 0;
}
& > *:last-child {
margin-bottom: 0 !important;
margin-bottom: 0;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { computed, ref, watchEffect } from 'vue'
import { type CompletionMenu, resolveSuggestMatches2Highlight } from './completion-menu'
import EditorMenu from '../../EditorMenu.vue'
import { determineClosestEdge, isElementInViewport } from '../../common'
import type { Icon, LayerContent } from '@/components/editor/code-editor/EditorUI'
import type { Action, Icon, LayerContent } from '@/components/editor/code-editor/EditorUI'
import DocumentPreview from '@/components/editor/code-editor/ui/features/hover-preview/DocumentPreview.vue'
import type { CompletionMenuFeatureItem } from '@/components/editor/code-editor/ui/features/completion-menu/completion'
import AudioPreview from '@/components/editor/code-editor/ui/features/hover-preview/AudioPreview.vue'
Expand Down Expand Up @@ -83,6 +83,10 @@ const activeCompletionMenuItem = computed<CompletionMenuFeatureItem | null>(() =
function handleMenuItemSelect(item: CompletionMenuItem) {
props.completionMenu.select(item.key)
}
function handleActionClick(action: Action) {
action.onClick()
}
</script>

<template>
Expand Down Expand Up @@ -127,6 +131,7 @@ function handleMenuItemSelect(item: CompletionMenuItem) {
:more-actions="activeCompletionMenuItem.preview.layer.moreActions"
:header="activeCompletionMenuItem.preview.layer.header"
:content="activeCompletionMenuItem.preview.layer.content"
@action-click="handleActionClick"
></DocumentPreview>
<AudioPreview
v-else-if="activeCompletionMenuItem?.preview?.type === 'audio'"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,17 @@ export class CompletionMenu implements IDisposable {
// attention! here we intercept `fire` function to prevent global `onDidChangeBlurWidget` active
// this is monaco inner function no need dispose manually
const rawFireFn = this.editorWidgetFocus._onDidChangeToFalse.fire
// This function runs when the Monaco Editor loses focus.
// It starts when Monaco's own completion menu is open,
// and the user clicks outside any Monaco HTML element.
// Our custom completion menu is separate from Monaco's, so clicking it moves focus from Monaco to our menu.
// This function makes sure clicking our menu doesn't change the focus,
// so users can use the menu (like selecting items with keys or pressing 'Enter'/'Tab' to insert words) without losing focus on the editor.
// If our custom menu is active, we stop the normal focus loss but keep original events working.
this.editorWidgetFocus._onDidChangeToFalse.fire = () => {
if (this.completionMenuState.focus) {
this.suggestControllerWidget._listElement?.firstElementChild.focus()
this.editor.focus()
} else {
rawFireFn.call(this.editorWidgetFocus._onDidChangeToFalse)
}
Expand Down
Loading

0 comments on commit 2f30643

Please sign in to comment.