feat: step 5 claimed done

This commit is contained in:
2026-04-27 22:36:53 +02:00
parent 0e1d8852f7
commit 2f09bf527d
20 changed files with 1740 additions and 115 deletions

View File

@@ -3272,6 +3272,57 @@ button svg * {
font-weight: 700;
}
.chat-panel-header {
position: relative;
}
.chat-panel-header-actions {
display: flex;
align-items: center;
gap: 10px;
}
.chat-model-selector-button,
.chat-model-selector-option {
border: 1px solid var(--line, #3c3c3c);
border-radius: 10px;
background: var(--panel-2, #252526);
color: inherit;
}
.chat-model-selector-button {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
}
.chat-model-selector-menu {
position: absolute;
top: calc(100% - 4px);
right: 20px;
min-width: 220px;
display: flex;
flex-direction: column;
gap: 6px;
padding: 10px;
border: 1px solid var(--line, #3c3c3c);
border-radius: 12px;
background: var(--panel-1, #1e1e1e);
box-shadow: 0 14px 36px rgba(0, 0, 0, 0.28);
z-index: 2;
}
.chat-model-selector-option {
width: 100%;
padding: 8px 10px;
text-align: left;
}
.chat-model-selector-option.active {
border-color: var(--accent-color);
}
.chat-messages {
padding: 20px;
overflow: auto;
@@ -3300,6 +3351,56 @@ button svg * {
background: rgba(0, 122, 204, 0.15);
}
.chat-tool-markers {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-bottom: 10px;
}
.chat-tool-marker {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 10px;
border-radius: 999px;
border: 1px solid var(--line, #3c3c3c);
background: rgba(255, 255, 255, 0.03);
font-size: 12px;
}
.chat-tool-surface {
max-width: min(820px, 100%);
margin-left: auto;
margin-right: auto;
border: 1px solid var(--line, #3c3c3c);
border-radius: 14px;
background: var(--panel-2, #252526);
padding: 16px;
}
.chat-tool-surface h3 {
margin: 0 0 12px;
}
.chat-tool-surface-table {
width: 100%;
border-collapse: collapse;
}
.chat-tool-surface-table th,
.chat-tool-surface-table td {
padding: 8px 10px;
border-bottom: 1px solid var(--line, #3c3c3c);
text-align: left;
}
.chat-tool-surface-json {
margin: 0;
white-space: pre-wrap;
font: 12px/1.5 "SFMono-Regular", Menlo, Monaco, Consolas, monospace;
}
.chat-input-container {
padding: 16px 20px 20px;
border-top: 1px solid var(--line, #3c3c3c);
@@ -3436,6 +3537,103 @@ button svg * {
font: 12px/1.5 "SFMono-Regular", Menlo, Monaco, Consolas, monospace;
}
.translation-validation-view,
.git-diff-view {
display: flex;
flex-direction: column;
gap: 16px;
min-height: 0;
}
.translation-validation-summary,
.translation-validation-section,
.git-diff-toolbar {
border: 1px solid var(--line, #3c3c3c);
border-radius: 12px;
background: var(--panel-2, #252526);
padding: 16px;
}
.translation-validation-summary p,
.git-diff-empty {
margin: 0;
color: var(--vscode-descriptionForeground);
}
.translation-validation-list {
display: grid;
gap: 12px;
margin-top: 12px;
}
.translation-validation-card {
border: 1px solid var(--line, #3c3c3c);
border-radius: 12px;
background: var(--panel-1, #1e1e1e);
padding: 16px;
}
.translation-validation-card-title {
margin: 0 0 12px;
font-weight: 600;
}
.translation-validation-card-meta {
margin: 0;
display: grid;
grid-template-columns: minmax(120px, 180px) minmax(0, 1fr);
gap: 8px 12px;
}
.translation-validation-card-meta dt {
color: var(--vscode-descriptionForeground);
}
.translation-validation-card-meta dd {
margin: 0;
word-break: break-word;
}
.translation-validation-actions {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.translation-validation-empty {
margin: 12px 0 0;
color: var(--vscode-descriptionForeground);
}
.git-diff-toolbar {
display: flex;
gap: 12px;
align-items: center;
flex-wrap: wrap;
}
.git-diff-toolbar label {
font-weight: 600;
}
.git-diff-toolbar select {
min-width: min(420px, 100%);
}
.git-diff-editor {
flex: 1;
min-height: 420px;
border: 1px solid var(--line, #3c3c3c);
border-radius: 12px;
overflow: hidden;
background: var(--panel-1, #1e1e1e);
}
.monaco-diff-editor-instance {
height: 100%;
min-height: 420px;
}
.linkish {
padding: 0;
border: none;

View File

@@ -238,6 +238,11 @@ document.addEventListener("DOMContentLoaded", () => {
document.head.appendChild(script);
});
const diffModelPath = (filePath, side) => {
const normalized = String(filePath || "working-tree").replace(/^\/+/, "");
return `inmemory://model/git-diff/${side}/${normalized}`;
};
const registerLiquidLanguage = (monaco) => {
if (liquidLanguageRegistered) {
return;
@@ -826,6 +831,134 @@ document.addEventListener("DOMContentLoaded", () => {
this.changeSubscription?.dispose();
this.editor?.dispose();
}
},
MonacoDiffEditor: {
mounted() {
this.host = this.el.querySelector(".monaco-diff-editor-instance");
this.originalInput = this.el.querySelector(".monaco-diff-original");
this.modifiedInput = this.el.querySelector(".monaco-diff-modified");
this.filePath = this.el.dataset.monacoDiffFilePath || "working-tree";
this.language = this.el.dataset.monacoDiffLanguage || "plaintext";
this.viewStyle = this.el.dataset.monacoDiffViewStyle || "inline";
this.wordWrap = this.el.dataset.monacoDiffWordWrap || "off";
this.hideUnchanged = this.el.dataset.monacoDiffHideUnchanged === "true";
this.readValues = () => ({
original: this.originalInput?.value || "",
modified: this.modifiedInput?.value || ""
});
this.applyDataset = () => {
this.filePath = this.el.dataset.monacoDiffFilePath || "working-tree";
this.language = this.el.dataset.monacoDiffLanguage || "plaintext";
this.viewStyle = this.el.dataset.monacoDiffViewStyle || "inline";
this.wordWrap = this.el.dataset.monacoDiffWordWrap || "off";
this.hideUnchanged = this.el.dataset.monacoDiffHideUnchanged === "true";
};
this.setModels = (monaco) => {
const values = this.readValues();
this.originalModel?.dispose();
this.modifiedModel?.dispose();
this.originalModel = monaco.editor.createModel(
values.original,
this.language,
monaco.Uri.parse(diffModelPath(this.filePath, "original"))
);
this.modifiedModel = monaco.editor.createModel(
values.modified,
this.language,
monaco.Uri.parse(diffModelPath(this.filePath, "modified"))
);
this.editor.setModel({ original: this.originalModel, modified: this.modifiedModel });
this.lastFilePath = this.filePath;
};
loadMonaco()
.then((monaco) => {
if (!this.host) {
return;
}
ensureMonacoTheme(monaco);
this.editor = monaco.editor.createDiffEditor(this.host, {
theme: "bds-theme",
automaticLayout: true,
readOnly: true,
renderSideBySide: this.viewStyle === "side-by-side",
minimap: { enabled: false },
scrollBeyondLastLine: false,
lineNumbers: "on",
diffCodeLens: false,
originalEditable: false,
wordWrap: this.wordWrap,
hideUnchangedRegions: { enabled: this.hideUnchanged },
ignoreTrimWhitespace: false
});
this.setModels(monaco);
})
.catch((error) => {
console.error("Failed to load Monaco diff editor", error);
});
},
updated() {
this.host = this.el.querySelector(".monaco-diff-editor-instance");
this.originalInput = this.el.querySelector(".monaco-diff-original");
this.modifiedInput = this.el.querySelector(".monaco-diff-modified");
this.applyDataset();
if (!this.editor) {
return;
}
loadMonaco().then((monaco) => {
ensureMonacoTheme(monaco);
monaco.editor.setTheme("bds-theme");
this.editor.updateOptions({
renderSideBySide: this.viewStyle === "side-by-side",
wordWrap: this.wordWrap,
hideUnchangedRegions: { enabled: this.hideUnchanged }
});
if (this.lastFilePath !== this.filePath) {
this.setModels(monaco);
return;
}
const values = this.readValues();
if (this.originalModel && this.originalModel.getLanguageId() !== this.language) {
monaco.editor.setModelLanguage(this.originalModel, this.language);
}
if (this.modifiedModel && this.modifiedModel.getLanguageId() !== this.language) {
monaco.editor.setModelLanguage(this.modifiedModel, this.language);
}
if (this.originalModel && this.originalModel.getValue() !== values.original) {
this.originalModel.setValue(values.original);
}
if (this.modifiedModel && this.modifiedModel.getValue() !== values.modified) {
this.modifiedModel.setValue(values.modified);
}
});
},
destroyed() {
this.originalModel?.dispose();
this.modifiedModel?.dispose();
this.editor?.dispose();
}
}
};