add system preview
This commit is contained in:
@@ -1,11 +1,19 @@
|
||||
import { ChevronDown, ChevronRight, Plus, Trash2, Undo2 } from 'lucide-react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { getLanguage } from 'obsidian';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { PREVIEW_VIEW_TYPE } from '../../constants';
|
||||
import { useApp } from '../../contexts/AppContext';
|
||||
import { useDiffStrategy } from '../../contexts/DiffStrategyContext';
|
||||
import { useRAG } from '../../contexts/RAGContext';
|
||||
import { useSettings } from '../../contexts/SettingsContext';
|
||||
import { CustomMode, GroupEntry, ToolGroup } from '../../database/json/custom-mode/types';
|
||||
import { useCustomModes } from '../../hooks/use-custom-mode';
|
||||
import { PreviewView, PreviewViewState } from '../../PreviewView';
|
||||
import { modes as buildinModes } from '../../utils/modes';
|
||||
import { openOrCreateMarkdownFile } from '../../utils/obsidian';
|
||||
import { PromptGenerator, getFullLanguageName } from '../../utils/prompt-generator';
|
||||
|
||||
const CustomModeView = () => {
|
||||
const app = useApp()
|
||||
|
||||
@@ -14,7 +22,16 @@ const CustomModeView = () => {
|
||||
deleteCustomMode,
|
||||
updateCustomMode,
|
||||
customModeList,
|
||||
customModePrompts
|
||||
} = useCustomModes()
|
||||
const { settings } = useSettings()
|
||||
const { getRAGEngine } = useRAG()
|
||||
const diffStrategy = useDiffStrategy()
|
||||
|
||||
const promptGenerator = useMemo(() => {
|
||||
// @ts-expect-error
|
||||
return new PromptGenerator(getRAGEngine, app, settings, diffStrategy, customModePrompts, customModeList)
|
||||
}, [app, settings, diffStrategy, customModePrompts, customModeList])
|
||||
|
||||
// 当前选择的模式
|
||||
const [selectedMode, setSelectedMode] = useState<string>('ask')
|
||||
@@ -326,8 +343,41 @@ const CustomModeView = () => {
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 预览和保存 */}
|
||||
<div className="infio-custom-modes-actions">
|
||||
<button className="infio-preview-btn">
|
||||
<button
|
||||
className="infio-preview-btn"
|
||||
onClick={async () => {
|
||||
let filesSearchMethod = settings.filesSearchMethod
|
||||
if (filesSearchMethod === 'auto' && settings.embeddingModelId && settings.embeddingModelId !== '') {
|
||||
filesSearchMethod = 'semantic'
|
||||
}
|
||||
|
||||
const userLanguage = getFullLanguageName(getLanguage())
|
||||
const systemPrompt = await promptGenerator.getSystemMessageNew(modeName, filesSearchMethod, userLanguage)
|
||||
const existingLeaf = app.workspace
|
||||
.getLeavesOfType(PREVIEW_VIEW_TYPE)
|
||||
.find(
|
||||
(leaf) =>
|
||||
leaf.view instanceof PreviewView && leaf.view.state.title === `${modeName} system prompt`
|
||||
)
|
||||
if (existingLeaf) {
|
||||
console.log(existingLeaf)
|
||||
app.workspace.setActiveLeaf(existingLeaf, { focus: true })
|
||||
} else {
|
||||
app.workspace.getLeaf(true).setViewState({
|
||||
type: PREVIEW_VIEW_TYPE,
|
||||
active: true,
|
||||
state: {
|
||||
content: systemPrompt.content as string,
|
||||
title: `${modeName} system prompt`,
|
||||
} satisfies PreviewViewState,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
>
|
||||
预览
|
||||
</button>
|
||||
<button
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
||||
import { ChevronDown, ChevronUp } from 'lucide-react'
|
||||
import React, { useEffect, useState, useMemo } from 'react'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
|
||||
import { useSettings } from '../../../contexts/SettingsContext'
|
||||
import { useCustomModes } from '../../../hooks/use-custom-mode'
|
||||
|
||||
105
src/components/preview-view/PreviewViewRoot.tsx
Normal file
105
src/components/preview-view/PreviewViewRoot.tsx
Normal file
@@ -0,0 +1,105 @@
|
||||
import { getIcon } from 'obsidian'
|
||||
import { useEffect, useRef } from 'react'
|
||||
|
||||
import { PreviewViewState } from '../../PreviewView'
|
||||
|
||||
export default function PreviewViewRoot({
|
||||
state,
|
||||
close,
|
||||
}: {
|
||||
state: PreviewViewState
|
||||
close: () => void
|
||||
}) {
|
||||
const closeIcon = getIcon('x')
|
||||
const contentRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
// 显示原始文本内容
|
||||
useEffect(() => {
|
||||
if (contentRef.current && state.content) {
|
||||
// 清空现有内容
|
||||
contentRef.current.empty()
|
||||
|
||||
// 创建预格式化文本元素
|
||||
const preElement = document.createElement('pre')
|
||||
preElement.className = 'infio-raw-content'
|
||||
preElement.textContent = state.content
|
||||
|
||||
// 添加到容器
|
||||
contentRef.current.appendChild(preElement)
|
||||
}
|
||||
}, [state.content, state.file])
|
||||
|
||||
return (
|
||||
<div id="infio-preview-view">
|
||||
<div className="view-header">
|
||||
<div className="view-header-left">
|
||||
<div className="view-header-nav-buttons"></div>
|
||||
</div>
|
||||
<div className="view-header-title-container mod-at-start">
|
||||
<div className="view-header-title">
|
||||
{state.title || (state.file ? state.file.name : 'Markdown Preview')}
|
||||
</div>
|
||||
<div className="view-actions">
|
||||
<button
|
||||
className="clickable-icon view-action infio-close-button"
|
||||
aria-label="Close preview"
|
||||
onClick={close}
|
||||
>
|
||||
{closeIcon && '✕'}
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="view-content">
|
||||
<div className="markdown-preview-view is-readable-line-width">
|
||||
<div className="markdown-preview-sizer">
|
||||
<div className="infio-preview-title">
|
||||
{state.title || (state.file ? state.file.name.replace(/\.[^/.]+$/, '') : '')}
|
||||
</div>
|
||||
<div
|
||||
ref={contentRef}
|
||||
className="markdown-preview-section"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<style>{`
|
||||
#infio-preview-view {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
background-color: var(--background-primary);
|
||||
}
|
||||
|
||||
#infio-preview-view .view-content {
|
||||
flex-grow: 1;
|
||||
overflow: auto;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.infio-preview-title {
|
||||
font-size: 1.8em;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
.markdown-preview-section {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.infio-raw-content {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
font-family: var(--font-monospace);
|
||||
padding: 10px;
|
||||
background-color: var(--background-secondary);
|
||||
border-radius: 4px;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user