Revert "feat: restyle utility panel and streaming focus"
This reverts commit 931a0488cc.
This commit is contained in:
parent
931a0488cc
commit
4cd4232c62
@ -536,7 +536,7 @@ class WebTerminal(MainTerminal):
|
|||||||
|
|
||||||
|
|
||||||
# 如果是聚焦操作,广播聚焦文件更新
|
# 如果是聚焦操作,广播聚焦文件更新
|
||||||
if tool_name in ['focus_file', 'unfocus_file', 'modify_file', 'append_to_file']:
|
if tool_name in ['focus_file', 'unfocus_file', 'modify_file']:
|
||||||
try:
|
try:
|
||||||
focused_files_dict = self.get_focused_files_info()
|
focused_files_dict = self.get_focused_files_info()
|
||||||
self.broadcast('focused_files_update', focused_files_dict)
|
self.broadcast('focused_files_update', focused_files_dict)
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="48" height="48" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="opacity:1;"><path d="M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z"/><path d="M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12"/><path d="M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 491 B |
@ -37,11 +37,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div :class="['main-container', { 'utility-panel-hidden': utilityPanelHidden }]">
|
<div class="main-container">
|
||||||
<ConversationSidebar
|
<ConversationSidebar
|
||||||
:icon-style="iconStyle"
|
:icon-style="iconStyle"
|
||||||
:format-time="formatTime"
|
:format-time="formatTime"
|
||||||
:utility-panel-hidden="utilityPanelHidden"
|
|
||||||
@toggle="toggleSidebar"
|
@toggle="toggleSidebar"
|
||||||
@create="createNewConversation"
|
@create="createNewConversation"
|
||||||
@search="handleSidebarSearch"
|
@search="handleSidebarSearch"
|
||||||
@ -50,7 +49,6 @@
|
|||||||
@personal="openPersonalPage"
|
@personal="openPersonalPage"
|
||||||
@delete="deleteConversation"
|
@delete="deleteConversation"
|
||||||
@duplicate="duplicateConversation"
|
@duplicate="duplicateConversation"
|
||||||
@toggle-utility-panel="toggleUtilityPanelVisibility"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<LeftPanel
|
<LeftPanel
|
||||||
@ -62,14 +60,12 @@
|
|||||||
:is-connected="isConnected"
|
:is-connected="isConnected"
|
||||||
:panel-menu-open="panelMenuOpen"
|
:panel-menu-open="panelMenuOpen"
|
||||||
:panel-mode="panelMode"
|
:panel-mode="panelMode"
|
||||||
:hidden="utilityPanelHidden"
|
|
||||||
@toggle-panel-menu="togglePanelMenu"
|
@toggle-panel-menu="togglePanelMenu"
|
||||||
@select-panel="selectPanelMode"
|
@select-panel="selectPanelMode"
|
||||||
@open-file-manager="openGuiFileManager"
|
@open-file-manager="openGuiFileManager"
|
||||||
@toggle-mode="toggleThinkingMode"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div v-if="!utilityPanelHidden" class="resize-handle" @mousedown="startResize('left', $event)"></div>
|
<div class="resize-handle" @mousedown="startResize('left', $event)"></div>
|
||||||
|
|
||||||
<main class="chat-container">
|
<main class="chat-container">
|
||||||
<TokenDrawer
|
<TokenDrawer
|
||||||
|
|||||||
@ -192,7 +192,6 @@ const appOptions = {
|
|||||||
...mapState(useFileStore, ['contextMenu', 'fileTree', 'expandedFolders', 'todoList']),
|
...mapState(useFileStore, ['contextMenu', 'fileTree', 'expandedFolders', 'todoList']),
|
||||||
...mapWritableState(useUiStore, [
|
...mapWritableState(useUiStore, [
|
||||||
'sidebarCollapsed',
|
'sidebarCollapsed',
|
||||||
'utilityPanelHidden',
|
|
||||||
'panelMode',
|
'panelMode',
|
||||||
'panelMenuOpen',
|
'panelMenuOpen',
|
||||||
'leftWidth',
|
'leftWidth',
|
||||||
@ -315,8 +314,6 @@ const appOptions = {
|
|||||||
uiSetPanelMode: 'setPanelMode',
|
uiSetPanelMode: 'setPanelMode',
|
||||||
uiSetPanelMenuOpen: 'setPanelMenuOpen',
|
uiSetPanelMenuOpen: 'setPanelMenuOpen',
|
||||||
uiTogglePanelMenu: 'togglePanelMenu',
|
uiTogglePanelMenu: 'togglePanelMenu',
|
||||||
uiToggleUtilityPanelHidden: 'toggleUtilityPanelHidden',
|
|
||||||
uiSetUtilityPanelHidden: 'setUtilityPanelHidden',
|
|
||||||
uiPushToast: 'pushToast',
|
uiPushToast: 'pushToast',
|
||||||
uiUpdateToast: 'updateToast',
|
uiUpdateToast: 'updateToast',
|
||||||
uiDismissToast: 'dismissToast',
|
uiDismissToast: 'dismissToast',
|
||||||
@ -1616,9 +1613,6 @@ const appOptions = {
|
|||||||
toggleSidebar() {
|
toggleSidebar() {
|
||||||
this.uiToggleSidebar();
|
this.uiToggleSidebar();
|
||||||
},
|
},
|
||||||
toggleUtilityPanelVisibility() {
|
|
||||||
this.uiToggleUtilityPanelHidden();
|
|
||||||
},
|
|
||||||
|
|
||||||
togglePanelMenu() {
|
togglePanelMenu() {
|
||||||
this.uiTogglePanelMenu();
|
this.uiTogglePanelMenu();
|
||||||
|
|||||||
@ -24,7 +24,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, watch } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useFocusStore } from '@/stores/focus';
|
import { useFocusStore } from '@/stores/focus';
|
||||||
|
|
||||||
@ -44,23 +44,4 @@ const focusedCount = computed(() => Object.keys(focusedFileMap.value).length);
|
|||||||
|
|
||||||
const languageClass = (path: string) => props.getLanguageClass(path);
|
const languageClass = (path: string) => props.getLanguageClass(path);
|
||||||
const formatSize = (size: number) => `${(size / 1024).toFixed(1)}KB`;
|
const formatSize = (size: number) => `${(size / 1024).toFixed(1)}KB`;
|
||||||
|
|
||||||
const refreshFocusedFiles = () => {
|
|
||||||
focusStore.fetchFocusedFiles().catch(() => {});
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
if (!props.collapsed) {
|
|
||||||
refreshFocusedFiles();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.collapsed,
|
|
||||||
collapsed => {
|
|
||||||
if (!collapsed) {
|
|
||||||
refreshFocusedFiles();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,10 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<aside
|
<aside class="sidebar left-sidebar" :style="{ width: width + 'px' }">
|
||||||
class="sidebar left-sidebar"
|
|
||||||
:class="{ 'panel-hidden': hidden }"
|
|
||||||
:style="panelStyles"
|
|
||||||
:aria-hidden="hidden ? 'true' : 'false'"
|
|
||||||
>
|
|
||||||
<div class="sidebar-status">
|
<div class="sidebar-status">
|
||||||
<div class="compact-status-card">
|
<div class="compact-status-card">
|
||||||
<div class="status-line">
|
<div class="status-line">
|
||||||
@ -16,14 +11,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="status-indicators">
|
<div class="status-indicators">
|
||||||
<button
|
<span class="mode-indicator" :class="{ thinking: thinkingMode, fast: !thinkingMode }">
|
||||||
type="button"
|
|
||||||
class="mode-indicator"
|
|
||||||
:class="{ thinking: thinkingMode, fast: !thinkingMode }"
|
|
||||||
:title="thinkingMode ? '切换到快速模式' : '切换到思考模式'"
|
|
||||||
:aria-pressed="thinkingMode ? 'true' : 'false'"
|
|
||||||
@click="$emit('toggle-mode')"
|
|
||||||
>
|
|
||||||
<transition name="mode-icon" mode="out-in">
|
<transition name="mode-icon" mode="out-in">
|
||||||
<span
|
<span
|
||||||
class="icon icon-sm"
|
class="icon icon-sm"
|
||||||
@ -32,7 +20,7 @@
|
|||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
></span>
|
></span>
|
||||||
</transition>
|
</transition>
|
||||||
</button>
|
</span>
|
||||||
<span class="connection-dot" :class="{ active: isConnected }" :title="isConnected ? '已连接' : '未连接'"></span>
|
<span class="connection-dot" :class="{ active: isConnected }" :title="isConnected ? '已连接' : '未连接'"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -134,7 +122,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import FileNode from '@/components/files/FileNode.vue';
|
import FileNode from '@/components/files/FileNode.vue';
|
||||||
import { useFileStore } from '@/stores/file';
|
import { useFileStore } from '@/stores/file';
|
||||||
@ -150,14 +138,12 @@ const props = defineProps<{
|
|||||||
isConnected: boolean;
|
isConnected: boolean;
|
||||||
panelMenuOpen: boolean;
|
panelMenuOpen: boolean;
|
||||||
panelMode: 'files' | 'todo' | 'subAgents';
|
panelMode: 'files' | 'todo' | 'subAgents';
|
||||||
hidden?: boolean;
|
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
defineEmits<{
|
defineEmits<{
|
||||||
(event: 'toggle-panel-menu'): void;
|
(event: 'toggle-panel-menu'): void;
|
||||||
(event: 'select-panel', mode: 'files' | 'todo' | 'subAgents'): void;
|
(event: 'select-panel', mode: 'files' | 'todo' | 'subAgents'): void;
|
||||||
(event: 'open-file-manager'): void;
|
(event: 'open-file-manager'): void;
|
||||||
(event: 'toggle-mode'): void;
|
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const panelMenuWrapper = ref<HTMLElement | null>(null);
|
const panelMenuWrapper = ref<HTMLElement | null>(null);
|
||||||
@ -170,15 +156,6 @@ const openSubAgent = (agent: any) => {
|
|||||||
subAgentStore.openSubAgent(agent);
|
subAgentStore.openSubAgent(agent);
|
||||||
};
|
};
|
||||||
|
|
||||||
const panelStyles = computed(() => {
|
|
||||||
const basis = props.hidden ? 0 : props.width;
|
|
||||||
return {
|
|
||||||
width: `${basis}px`,
|
|
||||||
minWidth: `${basis}px`,
|
|
||||||
flexBasis: `${basis}px`
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
panelMenuWrapper
|
panelMenuWrapper
|
||||||
});
|
});
|
||||||
|
|||||||
@ -54,20 +54,6 @@
|
|||||||
</slot>
|
</slot>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
v-if="collapsed"
|
|
||||||
type="button"
|
|
||||||
class="collapsed-control-btn utility-panel-toggle-btn"
|
|
||||||
:class="{ active: utilityPanelHidden }"
|
|
||||||
:title="utilityPanelHidden ? '显示工作面板' : '隐藏工作面板'"
|
|
||||||
@click="$emit('toggle-utility-panel')"
|
|
||||||
:aria-pressed="utilityPanelHidden ? 'true' : 'false'"
|
|
||||||
>
|
|
||||||
<span class="sr-only">{{ utilityPanelHidden ? '显示' : '隐藏' }}工作面板</span>
|
|
||||||
<span class="layers-icon" aria-hidden="true">
|
|
||||||
<span class="icon icon-md" :style="iconStyle('layers')"></span>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
@ -167,7 +153,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
defineOptions({ name: 'ConversationSidebar' });
|
defineOptions({ name: 'ConversationSidebar' });
|
||||||
|
|
||||||
import { computed } from 'vue';
|
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useUiStore } from '@/stores/ui';
|
import { useUiStore } from '@/stores/ui';
|
||||||
import { useConversationStore } from '@/stores/conversation';
|
import { useConversationStore } from '@/stores/conversation';
|
||||||
@ -176,7 +161,6 @@ import { usePersonalizationStore } from '@/stores/personalization';
|
|||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
formatTime?: (input: unknown) => string;
|
formatTime?: (input: unknown) => string;
|
||||||
iconStyle?: (key: string) => Record<string, string>;
|
iconStyle?: (key: string) => Record<string, string>;
|
||||||
utilityPanelHidden?: boolean;
|
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
defineEmits<{
|
defineEmits<{
|
||||||
@ -188,7 +172,6 @@ defineEmits<{
|
|||||||
(event: 'personal'): void;
|
(event: 'personal'): void;
|
||||||
(event: 'delete', id: string): void;
|
(event: 'delete', id: string): void;
|
||||||
(event: 'duplicate', id: string): void;
|
(event: 'duplicate', id: string): void;
|
||||||
(event: 'toggle-utility-panel'): void;
|
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const uiStore = useUiStore();
|
const uiStore = useUiStore();
|
||||||
@ -208,5 +191,4 @@ const { visible: personalPageVisible } = storeToRefs(personalizationStore);
|
|||||||
|
|
||||||
const formatTime = (value: unknown) => (props.formatTime ? props.formatTime(value) : String(value));
|
const formatTime = (value: unknown) => (props.formatTime ? props.formatTime(value) : String(value));
|
||||||
const iconStyle = (key: string) => (props.iconStyle ? props.iconStyle(key) : {});
|
const iconStyle = (key: string) => (props.iconStyle ? props.iconStyle(key) : {});
|
||||||
const utilityPanelHidden = computed(() => !!props.utilityPanelHidden);
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -48,7 +48,6 @@ interface EasterEggState {
|
|||||||
|
|
||||||
interface UiState {
|
interface UiState {
|
||||||
sidebarCollapsed: boolean;
|
sidebarCollapsed: boolean;
|
||||||
utilityPanelHidden: boolean;
|
|
||||||
panelMode: PanelMode;
|
panelMode: PanelMode;
|
||||||
panelMenuOpen: boolean;
|
panelMenuOpen: boolean;
|
||||||
leftWidth: number;
|
leftWidth: number;
|
||||||
@ -70,7 +69,6 @@ interface UiState {
|
|||||||
export const useUiStore = defineStore('ui', {
|
export const useUiStore = defineStore('ui', {
|
||||||
state: (): UiState => ({
|
state: (): UiState => ({
|
||||||
sidebarCollapsed: true,
|
sidebarCollapsed: true,
|
||||||
utilityPanelHidden: false,
|
|
||||||
panelMode: 'files',
|
panelMode: 'files',
|
||||||
panelMenuOpen: false,
|
panelMenuOpen: false,
|
||||||
leftWidth: 350,
|
leftWidth: 350,
|
||||||
@ -100,12 +98,6 @@ export const useUiStore = defineStore('ui', {
|
|||||||
setSidebarCollapsed(collapsed: boolean) {
|
setSidebarCollapsed(collapsed: boolean) {
|
||||||
this.sidebarCollapsed = collapsed;
|
this.sidebarCollapsed = collapsed;
|
||||||
},
|
},
|
||||||
setUtilityPanelHidden(hidden: boolean) {
|
|
||||||
this.utilityPanelHidden = hidden;
|
|
||||||
},
|
|
||||||
toggleUtilityPanelHidden() {
|
|
||||||
this.utilityPanelHidden = !this.utilityPanelHidden;
|
|
||||||
},
|
|
||||||
toggleSidebar() {
|
toggleSidebar() {
|
||||||
this.sidebarCollapsed = !this.sidebarCollapsed;
|
this.sidebarCollapsed = !this.sidebarCollapsed;
|
||||||
},
|
},
|
||||||
|
|||||||
@ -22,18 +22,6 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-container.utility-panel-hidden .messages-area {
|
|
||||||
max-width: 960px;
|
|
||||||
margin: 0 auto;
|
|
||||||
width: 100%;
|
|
||||||
padding-left: clamp(24px, 6vw, 72px);
|
|
||||||
padding-right: clamp(24px, 6vw, 72px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-container.utility-panel-hidden .message-block {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-container .input-area {
|
.chat-container .input-area {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|||||||
@ -1,17 +1,13 @@
|
|||||||
/* 聚焦文件 */
|
/* 聚焦文件 */
|
||||||
.focused-files {
|
.focused-files {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
background: rgba(255, 255, 255, 0.4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-files {
|
o-files {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: var(--claude-text-secondary);
|
color: var(--claude-text-secondary);
|
||||||
padding: 60px 20px;
|
padding: 60px 20px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
background: #fff;
|
|
||||||
border-radius: 12px;
|
|
||||||
border: 1px dashed var(--claude-border);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-tabs {
|
.file-tabs {
|
||||||
@ -21,21 +17,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.file-tab {
|
.file-tab {
|
||||||
border: 1px solid rgba(118, 103, 84, 0.15);
|
border: 1px solid var(--claude-border);
|
||||||
border-radius: 14px;
|
border-radius: 12px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #fff;
|
background: rgba(255, 255, 255, 0.75);
|
||||||
box-shadow: 0 10px 24px rgba(61, 57, 41, 0.08);
|
box-shadow: 0 12px 28px rgba(61, 57, 41, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-header {
|
.tab-header {
|
||||||
background: rgba(247, 244, 240, 0.9);
|
background: rgba(218, 119, 86, 0.08);
|
||||||
padding: 10px 18px;
|
padding: 10px 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
border-bottom: 1px solid rgba(118, 103, 84, 0.12);
|
border-bottom: 1px solid var(--claude-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-name {
|
.file-name {
|
||||||
@ -49,22 +45,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.file-content {
|
.file-content {
|
||||||
max-height: 340px;
|
max-height: 320px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
background: #fff;
|
background: #1e1e1e;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-content pre {
|
.file-content pre {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 16px 20px;
|
padding: 16px;
|
||||||
background: transparent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-content code {
|
.file-content code {
|
||||||
font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;
|
font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
color: #2c2c2c;
|
color: #aed581;
|
||||||
white-space: pre-wrap;
|
|
||||||
word-break: break-word;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,24 +23,6 @@
|
|||||||
.sidebar.left-sidebar {
|
.sidebar.left-sidebar {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
transition:
|
|
||||||
width 0.35s cubic-bezier(0.4, 0, 0.2, 1),
|
|
||||||
min-width 0.35s cubic-bezier(0.4, 0, 0.2, 1),
|
|
||||||
flex-basis 0.35s cubic-bezier(0.4, 0, 0.2, 1),
|
|
||||||
transform 0.35s ease,
|
|
||||||
opacity 0.35s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar.left-sidebar.panel-hidden {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(-80px);
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar.left-sidebar.panel-hidden .sidebar-status,
|
|
||||||
.sidebar.left-sidebar.panel-hidden .sidebar-panel-card-wrapper {
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.2s ease;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-status {
|
.sidebar-status {
|
||||||
@ -104,8 +86,6 @@
|
|||||||
color: #fffef8;
|
color: #fffef8;
|
||||||
box-shadow: 0 8px 20px rgba(189, 93, 58, 0.25);
|
box-shadow: 0 8px 20px rgba(189, 93, 58, 0.25);
|
||||||
transition: background 0.25s ease, box-shadow 0.25s ease, transform 0.25s ease;
|
transition: background 0.25s ease, box-shadow 0.25s ease, transform 0.25s ease;
|
||||||
border: none;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mode-indicator.fast {
|
.mode-indicator.fast {
|
||||||
@ -244,7 +224,6 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-panel-card .sidebar-header {
|
.sidebar-panel-card .sidebar-header {
|
||||||
|
|||||||
@ -142,34 +142,6 @@
|
|||||||
stroke-linejoin: round;
|
stroke-linejoin: round;
|
||||||
}
|
}
|
||||||
|
|
||||||
.utility-panel-toggle-btn {
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
border-radius: 24px;
|
|
||||||
border: none;
|
|
||||||
background: transparent;
|
|
||||||
color: #2f251b;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
transition: color 0.25s ease, transform 0.2s ease;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.utility-panel-toggle-btn .icon {
|
|
||||||
--icon-size: 22px;
|
|
||||||
display: inline-flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.utility-panel-toggle-btn:hover,
|
|
||||||
.utility-panel-toggle-btn:focus-visible {
|
|
||||||
color: var(--claude-accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
.utility-panel-toggle-btn.active {
|
|
||||||
color: #2f251b;
|
|
||||||
}
|
|
||||||
|
|
||||||
.new-conversation-btn {
|
.new-conversation-btn {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
background: linear-gradient(135deg, var(--claude-accent) 0%, var(--claude-accent-strong) 100%);
|
background: linear-gradient(135deg, var(--claude-accent) 0%, var(--claude-accent-strong) 100%);
|
||||||
|
|||||||
@ -9,14 +9,6 @@
|
|||||||
color: var(--claude-text);
|
color: var(--claude-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-container.utility-panel-hidden {
|
|
||||||
background: var(--claude-bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-container.utility-panel-hidden .chat-container {
|
|
||||||
background: rgba(255, 255, 255, 0.92);
|
|
||||||
}
|
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
min-height: var(--app-viewport, 100vh);
|
min-height: var(--app-viewport, 100vh);
|
||||||
background: var(--claude-bg);
|
background: var(--claude-bg);
|
||||||
|
|||||||
@ -17,7 +17,6 @@ export const ICONS = Object.freeze({
|
|||||||
hammer: '/static/icons/hammer.svg',
|
hammer: '/static/icons/hammer.svg',
|
||||||
info: '/static/icons/info.svg',
|
info: '/static/icons/info.svg',
|
||||||
laptop: '/static/icons/laptop.svg',
|
laptop: '/static/icons/laptop.svg',
|
||||||
layers: '/static/icons/layers.svg',
|
|
||||||
menu: '/static/icons/menu.svg',
|
menu: '/static/icons/menu.svg',
|
||||||
monitor: '/static/icons/monitor.svg',
|
monitor: '/static/icons/monitor.svg',
|
||||||
octagon: '/static/icons/octagon.svg',
|
octagon: '/static/icons/octagon.svg',
|
||||||
|
|||||||
@ -525,7 +525,7 @@ class WebTerminal(MainTerminal):
|
|||||||
|
|
||||||
|
|
||||||
# 如果是聚焦操作,广播聚焦文件更新
|
# 如果是聚焦操作,广播聚焦文件更新
|
||||||
if tool_name in ['focus_file', 'unfocus_file', 'modify_file', 'append_to_file']:
|
if tool_name in ['focus_file', 'unfocus_file', 'modify_file']:
|
||||||
try:
|
try:
|
||||||
focused_files_dict = self.get_focused_files_info()
|
focused_files_dict = self.get_focused_files_info()
|
||||||
self.broadcast('focused_files_update', focused_files_dict)
|
self.broadcast('focused_files_update', focused_files_dict)
|
||||||
|
|||||||
@ -2757,10 +2757,6 @@ async def handle_task_with_sender(terminal: WebTerminal, message, sender, client
|
|||||||
if refreshed.get("success"):
|
if refreshed.get("success"):
|
||||||
web_terminal.focused_files[path] = refreshed["content"]
|
web_terminal.focused_files[path] = refreshed["content"]
|
||||||
debug_log(f"聚焦文件已刷新: {path}")
|
debug_log(f"聚焦文件已刷新: {path}")
|
||||||
try:
|
|
||||||
sender('focused_files_update', web_terminal.get_focused_files_info())
|
|
||||||
except Exception as focus_exc:
|
|
||||||
debug_log(f"广播聚焦文件更新失败: {focus_exc}")
|
|
||||||
|
|
||||||
debug_log(f"追加写入完成: {summary}")
|
debug_log(f"追加写入完成: {summary}")
|
||||||
else:
|
else:
|
||||||
@ -3112,10 +3108,6 @@ async def handle_task_with_sender(terminal: WebTerminal, message, sender, client
|
|||||||
if refreshed.get("success"):
|
if refreshed.get("success"):
|
||||||
web_terminal.focused_files[path] = refreshed["content"]
|
web_terminal.focused_files[path] = refreshed["content"]
|
||||||
debug_log(f"聚焦文件已刷新: {path}")
|
debug_log(f"聚焦文件已刷新: {path}")
|
||||||
try:
|
|
||||||
sender('focused_files_update', web_terminal.get_focused_files_info())
|
|
||||||
except Exception as focus_exc:
|
|
||||||
debug_log(f"广播聚焦文件更新失败: {focus_exc}")
|
|
||||||
|
|
||||||
pending_modify = None
|
pending_modify = None
|
||||||
modify_probe_buffer = ""
|
modify_probe_buffer = ""
|
||||||
@ -4101,7 +4093,7 @@ async def handle_task_with_sender(terminal: WebTerminal, message, sender, client
|
|||||||
sender('update_action', update_payload)
|
sender('update_action', update_payload)
|
||||||
|
|
||||||
# 更新UI状态
|
# 更新UI状态
|
||||||
if function_name in ['focus_file', 'unfocus_file', 'modify_file', 'append_to_file']:
|
if function_name in ['focus_file', 'unfocus_file', 'modify_file']:
|
||||||
sender('focused_files_update', web_terminal.get_focused_files_info())
|
sender('focused_files_update', web_terminal.get_focused_files_info())
|
||||||
|
|
||||||
if function_name in ['create_file', 'delete_file', 'rename_file', 'create_folder']:
|
if function_name in ['create_file', 'delete_file', 'rename_file', 'create_folder']:
|
||||||
|
|||||||
@ -2662,10 +2662,6 @@ async def handle_task_with_sender(terminal: WebTerminal, message, sender, client
|
|||||||
if refreshed.get("success"):
|
if refreshed.get("success"):
|
||||||
web_terminal.focused_files[path] = refreshed["content"]
|
web_terminal.focused_files[path] = refreshed["content"]
|
||||||
debug_log(f"聚焦文件已刷新: {path}")
|
debug_log(f"聚焦文件已刷新: {path}")
|
||||||
try:
|
|
||||||
sender('focused_files_update', web_terminal.get_focused_files_info())
|
|
||||||
except Exception as focus_exc:
|
|
||||||
debug_log(f"广播聚焦文件更新失败: {focus_exc}")
|
|
||||||
|
|
||||||
debug_log(f"追加写入完成: {summary}")
|
debug_log(f"追加写入完成: {summary}")
|
||||||
else:
|
else:
|
||||||
@ -2965,8 +2961,7 @@ async def handle_task_with_sender(terminal: WebTerminal, message, sender, client
|
|||||||
summary_parts.append(apply_result["error"])
|
summary_parts.append(apply_result["error"])
|
||||||
|
|
||||||
matching_note = "提示:补丁匹配基于完整文本,包含注释和空白符,请确保 <<<OLD>>> 段落与文件内容逐字一致。如果修改成功,请忽略,如果失败,请明确原文后再次尝试。"
|
matching_note = "提示:补丁匹配基于完整文本,包含注释和空白符,请确保 <<<OLD>>> 段落与文件内容逐字一致。如果修改成功,请忽略,如果失败,请明确原文后再次尝试。"
|
||||||
if failed_blocks or not completed_blocks:
|
summary_parts.append(matching_note)
|
||||||
summary_parts.append(matching_note)
|
|
||||||
summary_message = " ".join(summary_parts).strip()
|
summary_message = " ".join(summary_parts).strip()
|
||||||
result["summary_message"] = summary_message
|
result["summary_message"] = summary_message
|
||||||
result["success"] = bool(completed_blocks) and not failed_blocks and apply_result.get("error") is None
|
result["success"] = bool(completed_blocks) and not failed_blocks and apply_result.get("error") is None
|
||||||
@ -3018,10 +3013,6 @@ async def handle_task_with_sender(terminal: WebTerminal, message, sender, client
|
|||||||
if refreshed.get("success"):
|
if refreshed.get("success"):
|
||||||
web_terminal.focused_files[path] = refreshed["content"]
|
web_terminal.focused_files[path] = refreshed["content"]
|
||||||
debug_log(f"聚焦文件已刷新: {path}")
|
debug_log(f"聚焦文件已刷新: {path}")
|
||||||
try:
|
|
||||||
sender('focused_files_update', web_terminal.get_focused_files_info())
|
|
||||||
except Exception as focus_exc:
|
|
||||||
debug_log(f"广播聚焦文件更新失败: {focus_exc}")
|
|
||||||
|
|
||||||
pending_modify = None
|
pending_modify = None
|
||||||
modify_probe_buffer = ""
|
modify_probe_buffer = ""
|
||||||
@ -4098,7 +4089,7 @@ async def handle_task_with_sender(terminal: WebTerminal, message, sender, client
|
|||||||
sender('update_action', update_payload)
|
sender('update_action', update_payload)
|
||||||
|
|
||||||
# 更新UI状态
|
# 更新UI状态
|
||||||
if function_name in ['focus_file', 'unfocus_file', 'modify_file', 'append_to_file']:
|
if function_name in ['focus_file', 'unfocus_file', 'modify_file']:
|
||||||
sender('focused_files_update', web_terminal.get_focused_files_info())
|
sender('focused_files_update', web_terminal.get_focused_files_info())
|
||||||
|
|
||||||
if function_name in ['create_file', 'delete_file', 'rename_file', 'create_folder']:
|
if function_name in ['create_file', 'delete_file', 'rename_file', 'create_folder']:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user