feat(diff): enable line-level patch selection and actions
Introduces granular control over diff operations by enabling users to select individual lines within a hunk. This refactors the core logic across multiple components, allowing for precise staging, unstaging, or discarding of specific changes rather than operating on entire hunks. The UI now features dedicated controls and visual feedback for line-level selection. - Refactored patch parsing to track selected line IDs and calculate range information. - Updated the diff view CSS and component structure to display interactive line selection bars. - Extended action dialogs to support confirming operations on selected lines.
This commit is contained in:
+75
-3
@@ -4167,11 +4167,37 @@
|
||||
|
||||
.line-patch-body {
|
||||
display: grid;
|
||||
grid-template-rows: minmax(0, 1fr);
|
||||
grid-template-rows: auto minmax(0, 1fr);
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.line-patch-selection-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 14px;
|
||||
min-height: 46px;
|
||||
padding: 7px 12px;
|
||||
border-bottom: 1px solid var(--color-border-subtle);
|
||||
background: var(--app-dialog-chrome);
|
||||
}
|
||||
.line-patch-selection-bar.active {
|
||||
background:
|
||||
linear-gradient(90deg, rgba(77, 182, 214, 0.1), transparent 44%),
|
||||
var(--app-dialog-chrome);
|
||||
}
|
||||
.line-patch-selection-bar > div:first-child {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
min-width: 0;
|
||||
color: var(--color-accent);
|
||||
}
|
||||
.line-patch-selection-bar strong { color: var(--color-ink); font-size: 11.5px; }
|
||||
.line-patch-selection-bar span { color: var(--color-ink-faint); font-size: 10px; }
|
||||
.line-patch-selected-actions { display: flex; align-items: center; justify-content: flex-end; gap: 6px; }
|
||||
|
||||
.line-patch-scroll {
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
@@ -4197,6 +4223,33 @@
|
||||
border-bottom: 1px solid var(--color-border-subtle);
|
||||
background: color-mix(in srgb, var(--code-surface-raised) 96%, transparent);
|
||||
}
|
||||
.line-patch-select-hunk,
|
||||
.line-patch-line-select {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
width: 16px;
|
||||
min-width: 16px;
|
||||
height: 16px;
|
||||
min-height: 16px;
|
||||
padding: 0;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 4px;
|
||||
color: #ffffff;
|
||||
background: var(--code-surface);
|
||||
box-shadow: none;
|
||||
}
|
||||
.line-patch-select-hunk:hover:not(:disabled),
|
||||
.line-patch-line-select:hover:not(:disabled) {
|
||||
border-color: rgba(77, 182, 214, 0.65);
|
||||
background: rgba(77, 182, 214, 0.1);
|
||||
}
|
||||
.line-patch-select-hunk.all,
|
||||
.line-patch-select-hunk.some,
|
||||
.line-patch-line-select[aria-pressed="true"] {
|
||||
border-color: rgba(77, 182, 214, 0.78);
|
||||
background: #238eb4;
|
||||
}
|
||||
.line-patch-select-hunk.some { background: rgba(35, 142, 180, 0.55); }
|
||||
.line-patch-hunk-head code {
|
||||
color: var(--color-accent);
|
||||
font-family: var(--font-mono);
|
||||
@@ -4242,12 +4295,17 @@
|
||||
|
||||
.line-patch-row {
|
||||
display: grid;
|
||||
grid-template-columns: 22px minmax(max-content, 1fr);
|
||||
grid-template-columns: 18px 38px 38px 22px minmax(max-content, 1fr);
|
||||
align-items: start;
|
||||
min-height: 22px;
|
||||
padding: 1px 10px 1px 28px;
|
||||
padding: 1px 10px 1px 8px;
|
||||
color: var(--color-ink-muted);
|
||||
}
|
||||
.line-patch-row.selectable { cursor: default; }
|
||||
.line-patch-row.selected {
|
||||
box-shadow: inset 3px 0 0 rgba(77, 182, 214, 0.86);
|
||||
filter: saturate(1.12) brightness(1.06);
|
||||
}
|
||||
.line-patch-row.add {
|
||||
background: var(--code-add-bg);
|
||||
color: var(--code-add-text);
|
||||
@@ -4264,12 +4322,26 @@
|
||||
text-align: center;
|
||||
user-select: none;
|
||||
}
|
||||
.line-patch-line-select { align-self: center; }
|
||||
.line-patch-line-select-placeholder { width: 16px; }
|
||||
.line-patch-line-number {
|
||||
padding-right: 7px;
|
||||
color: var(--color-ink-faint);
|
||||
font-size: 10px;
|
||||
line-height: 20px;
|
||||
text-align: right;
|
||||
user-select: none;
|
||||
}
|
||||
.line-patch-row.add .line-patch-prefix { color: var(--code-add-strong); }
|
||||
.line-patch-row.delete .line-patch-prefix { color: var(--code-delete-strong); }
|
||||
.line-patch-row code {
|
||||
white-space: pre;
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
@media (max-width: 760px) {
|
||||
.line-patch-selection-bar { align-items: stretch; flex-direction: column; }
|
||||
.line-patch-selected-actions { justify-content: flex-start; flex-wrap: wrap; }
|
||||
}
|
||||
|
||||
.blame-body {
|
||||
min-height: 0;
|
||||
|
||||
Reference in New Issue
Block a user