feat: step 5 claimed done
This commit is contained in:
198
priv/ui/app.css
198
priv/ui/app.css
@@ -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;
|
||||
|
||||
133
priv/ui/live.js
133
priv/ui/live.js
@@ -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();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user