mirror of
https://github.com/EthanMarti/infio-copilot.git
synced 2026-01-16 08:21:55 +00:00
add key short in edit inline
This commit is contained in:
parent
d15681b0d5
commit
76a5799067
@ -1,7 +1,7 @@
|
||||
import { Change, diffLines } from 'diff'
|
||||
import { CheckIcon, X } from 'lucide-react'
|
||||
import { getIcon } from 'obsidian'
|
||||
import { useState } from 'react'
|
||||
import { Platform, getIcon } from 'obsidian'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
import { ApplyViewState } from '../../ApplyView'
|
||||
import { useApp } from '../../contexts/AppContext'
|
||||
@ -17,6 +17,14 @@ export default function ApplyViewRoot({
|
||||
const rejectIcon = getIcon('x')
|
||||
const excludeIcon = getIcon('x')
|
||||
|
||||
const getShortcutText = (shortcut: 'accept' | 'reject') => {
|
||||
const isMac = Platform.isMacOS
|
||||
if (shortcut === 'accept') {
|
||||
return isMac ? '(⌘⏎)' : '(Ctrl+⏎)'
|
||||
}
|
||||
return isMac ? '(⌘⌫)' : '(Ctrl+⌫)'
|
||||
}
|
||||
|
||||
const app = useApp()
|
||||
|
||||
const [diff, setDiff] = useState<Change[]>(
|
||||
@ -64,6 +72,30 @@ export default function ApplyViewRoot({
|
||||
})
|
||||
}
|
||||
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
const modifierKey = Platform.isMacOS ? event.metaKey : event.ctrlKey;
|
||||
if (modifierKey) {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
handleAccept();
|
||||
} else if (event.key === 'Backspace') {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
handleReject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 在组件挂载时添加事件监听器,在卸载时移除
|
||||
useEffect(() => {
|
||||
const handler = (e: KeyboardEvent) => handleKeyDown(e);
|
||||
window.addEventListener('keydown', handler, true);
|
||||
return () => {
|
||||
window.removeEventListener('keydown', handler, true);
|
||||
}
|
||||
}, [handleAccept, handleReject]) // 添加handleAccept和handleReject作为依赖项
|
||||
|
||||
return (
|
||||
<div id="infio-apply-view">
|
||||
<div className="view-header">
|
||||
@ -81,7 +113,7 @@ export default function ApplyViewRoot({
|
||||
onClick={handleAccept}
|
||||
>
|
||||
{acceptIcon && <CheckIcon size={14} />}
|
||||
Accept
|
||||
Accept {getShortcutText('accept')}
|
||||
</button>
|
||||
<button
|
||||
className="clickable-icon view-action infio-reject-button"
|
||||
@ -89,7 +121,7 @@ export default function ApplyViewRoot({
|
||||
onClick={handleReject}
|
||||
>
|
||||
{rejectIcon && <X size={14} />}
|
||||
Reject
|
||||
Reject {getShortcutText('reject')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { MarkdownView, Plugin } from 'obsidian';
|
||||
import { MarkdownView, Plugin, Platform } from 'obsidian';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import { CornerDownLeft } from 'lucide-react';
|
||||
import { APPLY_VIEW_TYPE } from '../../constants';
|
||||
import LLMManager from '../../core/llm/manager';
|
||||
import { InfioSettings } from '../../types/settings';
|
||||
@ -20,24 +20,41 @@ type InlineEditProps = {
|
||||
type InputAreaProps = {
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
handleSubmit: () => void;
|
||||
handleClose: () => void;
|
||||
}
|
||||
|
||||
const InputArea: React.FC<InputAreaProps> = ({ value, onChange }) => {
|
||||
const InputArea: React.FC<InputAreaProps> = ({ value, onChange, handleSubmit, handleClose }) => {
|
||||
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// 组件挂载后自动聚焦到 textarea
|
||||
textareaRef.current?.focus();
|
||||
}, []);
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
if (e.key === 'Enter') {
|
||||
if (e.shiftKey) {
|
||||
// Shift + Enter: 允许换行,使用默认行为
|
||||
return;
|
||||
}
|
||||
// 普通 Enter: 阻止默认行为并触发提交
|
||||
e.preventDefault();
|
||||
handleSubmit();
|
||||
} else if (e.key === 'Escape') {
|
||||
// 当按下 Esc 键时关闭编辑器
|
||||
handleClose();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="infio-ai-block-input-wrapper">
|
||||
<textarea
|
||||
ref={textareaRef}
|
||||
className="infio-ai-block-content"
|
||||
placeholder="Enter instruction"
|
||||
placeholder="Input instruction, Enter to submit, Esc to close"
|
||||
value={value}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@ -91,7 +108,12 @@ const ControlArea: React.FC<ControlAreaProps> = ({
|
||||
onClick={onSubmit}
|
||||
disabled={isSubmitting}
|
||||
>
|
||||
{isSubmitting ? "Submitting..." : "Submit"}
|
||||
{isSubmitting ? "submitting..." : (
|
||||
<>
|
||||
submit
|
||||
<CornerDownLeft size={11} className="infio-ai-block-submit-icon" />
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</div>);
|
||||
};
|
||||
@ -251,9 +273,8 @@ export const InlineEdit: React.FC<InlineEditProps> = ({
|
||||
return (
|
||||
<div className="infio-ai-block-container"
|
||||
id="infio-ai-block-container"
|
||||
style={{ backgroundColor: 'var(--background-secondary)' }}
|
||||
>
|
||||
<InputArea value={instruction} onChange={setInstruction} />
|
||||
<InputArea value={instruction} onChange={setInstruction} handleSubmit={handleSubmit} handleClose={handleClose} />
|
||||
<button className="infio-ai-block-close-button" onClick={handleClose}>
|
||||
<svg
|
||||
width="14"
|
||||
|
||||
20
styles.css
20
styles.css
@ -1431,7 +1431,7 @@ input[type='text'].infio-chat-list-dropdown-item-title-input {
|
||||
}
|
||||
|
||||
.infio-ai-block-container {
|
||||
background: var(--background-secondary-alt);
|
||||
background: var(--background-secondary);
|
||||
border-radius: 4px;
|
||||
padding: 0px;
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
@ -1443,11 +1443,11 @@ input[type='text'].infio-chat-list-dropdown-item-title-input {
|
||||
}
|
||||
|
||||
.infio-ai-block-content {
|
||||
width: 80%;
|
||||
width: 100%;
|
||||
background: transparent;
|
||||
border: none !important;
|
||||
padding: 8px;
|
||||
padding-right: 40px;
|
||||
padding-right: 20px;
|
||||
height: 60px;
|
||||
resize: none;
|
||||
color: var(--text-normal);
|
||||
@ -1462,6 +1462,10 @@ input[type='text'].infio-chat-list-dropdown-item-title-input {
|
||||
}
|
||||
}
|
||||
|
||||
.infio-ai-block-content::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.infio-ai-block-close-button {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
@ -1655,6 +1659,14 @@ select.infio-ai-block-model-select::-ms-expand {
|
||||
}
|
||||
}
|
||||
|
||||
.infio-approve-button {
|
||||
background: rgba(var(--color-green-rgb), 0.7);
|
||||
}
|
||||
|
||||
.infio-reject-button {
|
||||
background: rgba(var(--color-red-rgb), 0.7);
|
||||
}
|
||||
|
||||
.infio-accept {
|
||||
background: rgba(var(--color-green-rgb), 0.7);
|
||||
box-shadow: inset 0 0 0 1000px rgba(0, 0, 0, 0.1);
|
||||
@ -1673,10 +1685,12 @@ select.infio-ai-block-model-select::-ms-expand {
|
||||
}
|
||||
|
||||
.view-actions {
|
||||
gap: 2px;
|
||||
button {
|
||||
color: var(--text-normal);
|
||||
font-weight: var(--font-medium);
|
||||
gap: 2px;
|
||||
border-radius: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user