✨ feat(vscode): 只有从「未提交的更改」点开的预览才对比上一次提交
This commit is contained in:
1 parent
4ec2b9d5d6
commit
3c7513b7cd
18 files changed
+366
-143
No files matched your search
@@ -72,7 +72,7 @@ export function App(): ReactElement | null {
|
||||
const [keep, setKeep] = useState<ReadonlySet<string>>(NONE)
|
||||
/** 页面上这个文档版本的中文名:文档带来的,扩展端查到了再换 */
|
||||
const [names, setNames] = useState<VersionNames | undefined>()
|
||||
/** 这份文件相比对比基准改了什么:审查工作副本里的、工作区仓库里有改动的文件扩展端算好了补来,不比时是 null */
|
||||
/** 这份文件相比对比基准改了什么:审查工作副本里的、从「未提交的更改」点开的有改动的文件扩展端算好了补来,不比时是 null */
|
||||
const [diff, setDiff] = useState<DocumentDiff | null>(null)
|
||||
/** 收到消息时读眼下哪些块在编辑(消息回调只在挂载时注册一次) */
|
||||
const editing = useRef(view.editing)
|
||||
@@ -177,11 +177,16 @@ export function App(): ReactElement | null {
|
||||
case 'diff':
|
||||
setDiff(msg.diff)
|
||||
return
|
||||
case 'openedFrom':
|
||||
viewState.update({ openedFrom: msg.from })
|
||||
return
|
||||
case 'focusPathAsk':
|
||||
setPathFocus(n => n + 1)
|
||||
}
|
||||
})
|
||||
postMessage({ type: 'ready' })
|
||||
// 重启 VS Code 后恢复的标签页,扩展端不知道它是从哪儿打开的,按页面记着的
|
||||
const { openedFrom } = viewState.get()
|
||||
postMessage({ type: 'ready', ...(openedFrom && { openedFrom }) })
|
||||
return off
|
||||
}, [])
|
||||
|
||||
|
||||
@@ -448,6 +448,9 @@ export interface StickyScrollSettings {
|
||||
maxLineCount: number
|
||||
}
|
||||
|
||||
/** 这个标签页是从哪儿打开的:从侧栏「未提交的更改」一栏点开的是 `uncommitted`,别处打开的是 `other`;页面只记着,重启 VS Code 后恢复时报给扩展端。 */
|
||||
export type OpenedFrom = 'uncommitted' | 'other'
|
||||
|
||||
/**
|
||||
* reveal:已经开着的预览滚到某处(同 DocumentMessage.reveal)
|
||||
* definitionProbed:id 那次 probeDefinition 的回答,found 表示查得到定义
|
||||
@@ -464,7 +467,8 @@ export interface StickyScrollSettings {
|
||||
* rewriteEnd:askId 那一轮重写结束了,见 RewriteEnd:done 是模型答完、记下了(没写进文件时带原因);failed、stopped 没记,文件没改
|
||||
* moveOccurrence:跳到高亮着的名字的下一处(step 1)/ 上一处(step -1)出现
|
||||
* displayNames:version 这份文档里显示成中文名的名字,查到一步来一步;不是页面上这个版本的不理
|
||||
* diff:这份文件相比对比基准改了什么(审查工作副本里的、工作区仓库里有改动的文件才有);每来一份文档之后补来,基准变了再来;null 是不比了
|
||||
* diff:这份文件相比对比基准改了什么(审查工作副本里的、从「未提交的更改」点开的有改动的文件才有);每来一份文档之后补来,基准变了、换了从哪儿打开再来;null 是不比了
|
||||
* openedFrom:这个标签页是从哪儿打开的,记进页面状态;ready 后来一次,开着时又被点开再来
|
||||
* repoLinksChecked:id 那次 checkRepoLinks 的回答,missing 是仓库里没有的路径,unresolved 是找不到的不带路径的引用
|
||||
* repoLinkBroken:这个仓库链接打不开。没有 symbol 是文件或目录没有;有 symbol 是文件在、这个符号没有;没有 path 是不带路径的引用找不到
|
||||
* repoLinkOpened:这个仓库链接打开了。路径在;带了 symbol 时这个符号也在;没有 path 是不带路径的引用找到了
|
||||
@@ -530,6 +534,7 @@ export type ExtensionToWebview
|
||||
| { type: 'rewriteProgress', askId: string, question: string, text: string, activity?: string, queued?: true }
|
||||
| RewriteEnd
|
||||
| { type: 'diff', diff: DocumentDiff | null }
|
||||
| { type: 'openedFrom', from: OpenedFrom }
|
||||
| { type: 'repoLinksChecked', id: number, missing: string[], unresolved: string[] }
|
||||
| { type: 'repoLinkBroken', path?: string, symbol?: string }
|
||||
| { type: 'repoLinkOpened', path?: string, symbol?: string }
|
||||
@@ -539,6 +544,7 @@ export type ExtensionToWebview
|
||||
| { type: 'callTree', version: number, anchor: string, name: string, where: string, trees: CallTree[], contractMiss?: ContractMiss }
|
||||
|
||||
/**
|
||||
* ready:页面准备好了,可以收消息;openedFrom 是页面状态里记着的这个标签页是从哪儿打开的,新开的页面没记过就不带
|
||||
* edit:把 startLine..endLine 这几行整行替换成 text(扩展端给每行补回原来第一行的缩进)
|
||||
* visibleLine:视口顶部那块的起始行,切回文本编辑器时扩展端把这行放到顶部
|
||||
* probeDefinition:按住 ⌘ / Ctrl 指到带下标的名字上,问 offset 处有没有定义;id 标出是哪一次问,回答带回来;
|
||||
@@ -568,7 +574,7 @@ export type ExtensionToWebview
|
||||
* goToCallNode:点了调用树上的一个节点,打开 uri 那个文件,跳到 line 行 character 列(见 CallTreeNode.jump)
|
||||
*/
|
||||
export type WebviewToExtension
|
||||
= | { type: 'ready' }
|
||||
= | { type: 'ready', openedFrom?: OpenedFrom }
|
||||
| { type: 'setFilter', excluded: Excluded }
|
||||
| { type: 'setOnlyChanges', on: boolean }
|
||||
| { type: 'edit', startLine: number, endLine: number, text: string }
|
||||
|
||||
@@ -62,6 +62,14 @@ describe('webview 状态', () => {
|
||||
expect(createViewStateStore(memoryStorage(null)).get()).toEqual({ editing: [], folds: {} })
|
||||
})
|
||||
|
||||
it('记着这个标签页是从哪儿打开的,页面重新加载后取回;认不得的值当没记过', () => {
|
||||
const storage = memoryStorage()
|
||||
createViewStateStore(storage).update({ openedFrom: 'uncommitted' })
|
||||
expect(createViewStateStore(storage).get()).toEqual({ editing: [], folds: {}, openedFrom: 'uncommitted' })
|
||||
expect(createViewStateStore(memoryStorage({ openedFrom: 'other' })).get()).toEqual({ editing: [], folds: {}, openedFrom: 'other' })
|
||||
expect(createViewStateStore(memoryStorage({ openedFrom: 'files' })).get()).toEqual({ editing: [], folds: {} })
|
||||
})
|
||||
|
||||
it('属性行的折叠 id 是块 id 加行序号,不会和块 id 撞上', () => {
|
||||
expect(propertyRowId('6.1.0', 3)).toBe('6.1.0/p3')
|
||||
expect(propertyRowId('6', 1)).not.toBe('6.1')
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
import type { ScrollAnchor } from './scrollPosition'
|
||||
import type { BlockView } from './types'
|
||||
import type { BlockView, OpenedFrom } from './types'
|
||||
|
||||
/**
|
||||
* 标签页切走时 VS Code 会销毁 webview、切回来重新加载,靠它恢复:哪些块停在「编辑」、
|
||||
* 用户把哪些块、属性行和子行折叠 / 展开了(块 id 是它在树里的位置,文档刷新后照旧对得上;属性行、子行 id 见 propertyRowId、propertyItemId),以及滚到了哪。
|
||||
* 用户把哪些块、属性行和子行折叠 / 展开了(块 id 是它在树里的位置,文档刷新后照旧对得上;属性行、子行 id 见 [propertyRowId]、[propertyItemId]),以及滚到了哪。
|
||||
* VS Code 重启后恢复标签页时也带着它,这个标签页是从哪儿打开的靠它报回扩展端。
|
||||
*/
|
||||
export interface ViewState {
|
||||
editing: string[]
|
||||
/** 用户自己点过折叠箭头的块、属性行和子行:id → 折叠着没有。没点过的按默认,见 collapsedIds */
|
||||
folds: Record<string, boolean>
|
||||
scroll?: ScrollAnchor
|
||||
/** 这个标签页是从哪儿打开的,扩展端告诉的;新开的页面还没记 */
|
||||
openedFrom?: OpenedFrom
|
||||
}
|
||||
|
||||
export interface ViewStateStorage {
|
||||
@@ -51,7 +54,12 @@ function readViewState(saved: unknown): ViewState {
|
||||
const folds = isRecord(state.folds)
|
||||
? Object.fromEntries(Object.entries(state.folds).filter((entry): entry is [string, boolean] => typeof entry[1] === 'boolean'))
|
||||
: {}
|
||||
return isScrollAnchor(state.scroll) ? { editing, folds, scroll: state.scroll } : { editing, folds }
|
||||
return {
|
||||
editing,
|
||||
folds,
|
||||
...(isScrollAnchor(state.scroll) && { scroll: state.scroll }),
|
||||
...((state.openedFrom === 'uncommitted' || state.openedFrom === 'other') && { openedFrom: state.openedFrom }),
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user