✨ feat(vscode): 预览里代码的上色和卡片种类色跟着当前颜色主题走
This commit is contained in:
1 parent
19302bbed0
commit
dff38ee0c5
26 files changed
+1286
-75
No files matched your search
@@ -12,6 +12,7 @@ import type { DocumentDiff } from '../diff/previewDiff'
|
||||
import type { ShownName } from '../nameResolution'
|
||||
import type { ProfileChoice } from '../qa/askProfiles'
|
||||
import type { AskRound } from '../qa/asks'
|
||||
import type { CodeColors } from '../theme/codeColors'
|
||||
import type { Excluded, FilterState } from './blockFilter'
|
||||
|
||||
export type { Excluded, ShownName }
|
||||
@@ -138,6 +139,8 @@ export interface StickyScrollSettings {
|
||||
* stickyScroll:VS Code 的 Sticky Scroll 设置(按这份文件取,语言自己的设置优先),见 StickyScrollSettings;ready 后发一次,设置改了再发
|
||||
* occurrencesFound:id 那次 findOccurrences 的回答,语言扩展没答(或没装)就是空的
|
||||
* filter:整个工作区共用的块筛选和「只看改动」开关;ready 后先于第一份文档发一次,之后任何一个预览改了都发给所有预览
|
||||
* codeColors:当前颜色主题(叠上用户设置里改的)给代码的配色,见 CodeColors,页面设成词性、种类的颜色变量;
|
||||
* ready 后先于第一份文档发一次,换了颜色主题、改了代码配色的设置再发给所有预览
|
||||
* qa:这份文件的问答;ready 后发一次,问答、正在答的问题变了再发
|
||||
* profiles:kind 那种对话输入框旁边的 profile 下拉:选项和选中的那项;ready 后两种各发一次,任何一个预览改了哪种就把哪种发给所有预览
|
||||
* answer:askId 那个问题的回答长了(text 是到现在为止的全文)、或换了在做的事
|
||||
@@ -170,6 +173,7 @@ export type ExtensionToWebview
|
||||
| { type: 'moveOccurrence', step: 1 | -1 }
|
||||
| { type: 'displayNames', version: number, names: ShownName[] }
|
||||
| ({ type: 'filter' } & FilterState)
|
||||
| ({ type: 'codeColors' } & CodeColors)
|
||||
| QaMessage
|
||||
| ({ type: 'profiles', kind: ChatKind } & ProfileChoice)
|
||||
| { type: 'answer', askId: string, text: string, activity?: string }
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { DiffBase, OpenedFrom } from '../diff/diffBase'
|
||||
import type { ProfileChoice } from '../qa/askProfiles'
|
||||
import type { RewriteRequest } from '../qa/codeQa'
|
||||
import type { SymbolNode } from '../symbolLinks'
|
||||
import type { CodeColors } from '../theme/codeColors'
|
||||
import type { ExtensionToWebview, WebviewToExtension } from './messages'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { window, workspace } from 'vscode'
|
||||
@@ -62,6 +63,7 @@ function preview(rewrite: (uri: unknown, request: RewriteRequest) => Promise<str
|
||||
{},
|
||||
{},
|
||||
{ subscribe },
|
||||
{ subscribe },
|
||||
async () => [],
|
||||
qa,
|
||||
async () => [],
|
||||
@@ -162,8 +164,27 @@ function profileSet(selected: string) {
|
||||
}
|
||||
}
|
||||
|
||||
const COLORS = { roles: { keyword: '#C586C0' }, kinds: { loop: '#C586C0' } } as unknown as CodeColors
|
||||
|
||||
/** 共用的代码配色:眼下是 colors,publish 模拟换了颜色主题、通知订阅的预览 */
|
||||
function themeColors(colors: CodeColors) {
|
||||
const listeners = new Set<(value: CodeColors) => void>()
|
||||
let current = colors
|
||||
return {
|
||||
current: async () => current,
|
||||
subscribe: (listener: (value: CodeColors) => void) => {
|
||||
listeners.add(listener)
|
||||
return { dispose: () => listeners.delete(listener) }
|
||||
},
|
||||
publish: (value: CodeColors) => {
|
||||
current = value
|
||||
listeners.forEach(listener => listener(value))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/** 对比基准只认从「未提交的更改」点开的:从那儿点开的对比上一次提交,别处打开的不比 */
|
||||
function opening(profiles = { ask: profileSet(''), rewrite: profileSet('') }) {
|
||||
function opening(profiles = { ask: profileSet(''), rewrite: profileSet('') }, colors = themeColors(COLORS)) {
|
||||
const subscribe = () => ({ dispose: () => {} })
|
||||
const diffBase = vi.fn((_uri: unknown, from: OpenedFrom): DiffBase | undefined => from === 'uncommitted' ? HEAD_BASE : undefined)
|
||||
const qa = {
|
||||
@@ -179,6 +200,7 @@ function opening(profiles = { ask: profileSet(''), rewrite: profileSet('') }) {
|
||||
{},
|
||||
{},
|
||||
{ subscribe, current: { excluded: {}, onlyChanges: false } },
|
||||
colors,
|
||||
async () => [],
|
||||
qa,
|
||||
async () => [],
|
||||
@@ -314,6 +336,28 @@ describe('预览对比什么看这个标签页是从哪儿打开的', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('代码配色跟着当前颜色主题', () => {
|
||||
it('ready 后先于第一份文档发;换了主题发给 ready 了的预览,还没 ready 的等 ready 时发眼下的', async () => {
|
||||
const colors = themeColors(COLORS)
|
||||
const { provider, document } = opening(undefined, colors)
|
||||
const page = tab()
|
||||
provider.resolveCustomTextEditor(document as never, page.panel)
|
||||
const light = { roles: { keyword: '#AF00DB' }, kinds: { loop: '#AF00DB' } } as unknown as CodeColors
|
||||
colors.publish(light)
|
||||
expect(page.posted()).toEqual([])
|
||||
|
||||
await page.send({ type: 'ready' })
|
||||
const types = page.posted().map(message => message.type)
|
||||
expect(page.posted()).toContainEqual({ type: 'codeColors', ...light })
|
||||
expect(types.indexOf('codeColors')).toBeGreaterThanOrEqual(0)
|
||||
expect(types.indexOf('codeColors')).toBeLessThan(types.indexOf('document'))
|
||||
|
||||
page.clear()
|
||||
colors.publish(COLORS)
|
||||
expect(page.posted()).toEqual([{ type: 'codeColors', ...COLORS }])
|
||||
})
|
||||
})
|
||||
|
||||
describe('问 AI 和重写注释的 profile 下拉各管各的', () => {
|
||||
it('ready 后两套各发一次;哪一套变了只发哪一套', async () => {
|
||||
const profiles = { ask: profileSet('sonnet'), rewrite: profileSet('dsflash') }
|
||||
|
||||
@@ -12,6 +12,7 @@ import type { CodeReaderRegistry } from '../registry'
|
||||
import type { LookupSources } from '../ruleLookups'
|
||||
import type { TreeSitterRuntime } from '../runtime'
|
||||
import type { ImportedName, LinkTarget, SymbolNode } from '../symbolLinks'
|
||||
import type { ThemeColors } from '../theme/codeColors'
|
||||
import type { BlockFilter } from './blockFilter'
|
||||
import type { FoundLocation } from './definitions'
|
||||
import type { ChatKind, DefinitionPeek, ExtensionToWebview, Occurrence, Reveal, SymbolReference, WebviewToExtension } from './messages'
|
||||
@@ -82,6 +83,8 @@ export class PreviewEditorProvider implements CustomTextEditorProvider {
|
||||
private readonly registry: CodeReaderRegistry,
|
||||
private readonly runtime: TreeSitterRuntime,
|
||||
private readonly filter: BlockFilter,
|
||||
/** 代码配色:各预览共用当前颜色主题的那一份,换了主题、改了代码配色的设置时发给订阅的 */
|
||||
readonly codeColors: Pick<ThemeColors, 'current' | 'subscribe'>,
|
||||
/** 库规则标的引用去哪儿查定义(交给标它的规则) */
|
||||
readonly resolveReference: (reference: RuleReference) => Promise<RuleLocation[]>,
|
||||
/** 问 AI:各预览共用,同一份文件开在几处时问答、正在答的问题都一样 */
|
||||
@@ -284,6 +287,11 @@ class Preview {
|
||||
if (this.ready)
|
||||
this.post({ type: 'filter', ...state })
|
||||
}),
|
||||
// 同上:没 ready 的等 ready 时在第一份文档之前发眼下的
|
||||
owner.codeColors.subscribe((colors) => {
|
||||
if (this.ready)
|
||||
this.post({ type: 'codeColors', ...colors })
|
||||
}),
|
||||
// 项目的入口变了:重新发文档,卡片左边的入口图标跟着变
|
||||
owner.entries.onDidChange((uris) => {
|
||||
if (uris.some(uri => uri.toString() === document.uri.toString()))
|
||||
@@ -605,6 +613,8 @@ class Preview {
|
||||
this.postQa()
|
||||
for (const kind of CHAT_KINDS)
|
||||
void this.postProfiles(kind)
|
||||
// 也先于文档发:第一份文档一画出来就是主题的颜色,不会先没颜色再闪一下
|
||||
this.post({ type: 'codeColors', ...await this.owner.codeColors.current() })
|
||||
await this.push()
|
||||
if (this.pendingPathFocus)
|
||||
this.focusPathAsk()
|
||||
|
||||
Reference in new issue
Block a user