Skip to content

Commit 3e6e162

Browse files
committed
another pr files optimization
1 parent bc9003f commit 3e6e162

7 files changed

Lines changed: 171 additions & 92 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ build
2828
deploy
2929
gitly_linux
3030
gitly_ci
31+
gitly.sqlite*

diff.v

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,12 @@ fn diff_hunk_header_html(header string) string {
2424
}
2525

2626
fn diff_line_row_html(file_path string, dline DiffLine) string {
27-
return '<p class=${dline.compact_class()}><u>${dline.old_line_str()}</u><u>${dline.new_line_str()}</u><i>${dline.compact_sign()}</i><s>${highlight.highlight_line(dline.content,
28-
file_path)}</s></p>'
27+
return diff_line_row_html_with_attrs(file_path, dline, '')
2928
}
3029

31-
fn diff_comment_box_html(file_path string, dline DiffLine, lang Lang) string {
32-
if dline.kind == 'context' {
33-
return ''
34-
}
35-
name := html_escape_text(dline.comment_field_name(file_path))
36-
placeholder := html_escape_text(veb.tr(lang.str(), 'pr_line_comment_placeholder').trim_space())
37-
return '<p class=m><textarea name="${name}" placeholder="${placeholder}" rows=2></textarea></p>'
30+
fn diff_line_row_html_with_attrs(file_path string, dline DiffLine, attrs string) string {
31+
return '<p class=${dline.compact_class()}${attrs}><u>${dline.old_line_str()}</u><u>${dline.new_line_str()}</u><i>${dline.compact_sign()}</i><s>${highlight.highlight_line(dline.content,
32+
file_path)}</s></p>'
3833
}
3934

4035
struct FileDiff {
@@ -176,6 +171,14 @@ fn (d &DiffLine) compact_class() string {
176171
}
177172
}
178173

174+
fn (d &DiffLine) compact_side() string {
175+
return match d.kind {
176+
'add' { 'n' }
177+
'del' { 'o' }
178+
else { '' }
179+
}
180+
}
181+
179182
fn (d &DiffLine) side() string {
180183
return if d.kind == 'add' { 'new' } else { 'old' }
181184
}

pr_routes.v

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,35 @@ struct PrFileTreeRow {
5252
deletions int
5353
}
5454

55+
fn render_pr_file_tree(file_tree []PrFileTreeRow) veb.RawHtml {
56+
mut out := strings.new_builder(file_tree.len * 160)
57+
for row in file_tree {
58+
path := html_escape_text(row.path)
59+
name := html_escape_text(row.name)
60+
indent := row.indent_px
61+
if row.is_dir {
62+
out.write_string('<button type=button class="r d" q="${path}" style="--i:${indent}px" aria-expanded=true><b></b><span>${name}</span></button>')
63+
} else {
64+
status := row.status()
65+
out.write_string('<a class="r f" href="#diff-${path}" p="${path}" style="--i:${indent}px" title="${path}"><b></b><span>${name}</span><em>${status}</em><small><b>+${row.additions}</b><i>-${row.deletions}</i></small></a>')
66+
}
67+
}
68+
return veb.RawHtml(out.str())
69+
}
70+
71+
fn (row PrFileTreeRow) status() string {
72+
if row.is_new {
73+
return 'A'
74+
}
75+
if row.is_deleted {
76+
return 'D'
77+
}
78+
if row.is_renamed {
79+
return 'R'
80+
}
81+
return 'M'
82+
}
83+
5584
fn build_pr_file_tree_rows(file_diffs []FileDiff) []PrFileTreeRow {
5685
mut sorted := file_diffs.clone()
5786
sorted.sort(a.path < b.path)
@@ -605,16 +634,18 @@ fn merge_branches_in_bare(repo Repo, base string, head string, author string, me
605634
return commit_sha
606635
}
607636

608-
fn render_pr_diff_table(fd FileDiff, comments_by_key map[string][]PrReviewCommentWithUser, can_comment bool, lang Lang) veb.RawHtml {
637+
fn render_pr_diff_table(fd FileDiff, comments_by_key map[string][]PrReviewCommentWithUser, can_comment bool) veb.RawHtml {
609638
mut out := strings.new_builder(1024)
610639
out.write_string('<div class=pr-diff__table>')
611640
for hunk in fd.hunks {
612641
out.write_string(diff_hunk_header_html(hunk.header))
613642
for dline in hunk.lines {
614-
out.write_string(diff_line_row_html(fd.path, dline))
615-
if can_comment && dline.kind != 'context' {
616-
out.write_string(diff_comment_box_html(fd.path, dline, lang))
643+
attrs := if can_comment && dline.kind != 'context' {
644+
' s=${dline.compact_side()} l=${dline.effective_line()}'
645+
} else {
646+
''
617647
}
648+
out.write_string(diff_line_row_html_with_attrs(fd.path, dline, attrs))
618649
out.write_string(inline_comments_html(fd.path, dline, comments_by_key))
619650
}
620651
}

static/assets/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
17255ce
1+
bc9003f

static/css/gitly.scss

Lines changed: 55 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2355,14 +2355,14 @@ form {
23552355
}
23562356
}
23572357

2358-
.pr-file-tree-row {
2358+
.pr-files-sidebar__list > .r {
23592359
display: grid;
23602360
grid-template-columns: 16px 18px minmax(0, 1fr) auto auto;
23612361
align-items: center;
23622362
gap: 7px;
23632363
width: 100% !important;
23642364
box-sizing: border-box;
2365-
padding: 6px 10px;
2365+
padding: 6px 10px 6px var(--i, 10px);
23662366
border-top: 1px solid #eef1f4;
23672367
border-right: 0;
23682368
border-bottom: 0;
@@ -2387,20 +2387,18 @@ form {
23872387
}
23882388
}
23892389

2390-
.pr-file-tree-row[hidden],
2390+
.pr-files-sidebar__list > .r[hidden],
23912391
.pr-files-filter-empty[hidden] {
23922392
display: none !important;
23932393
}
23942394

2395-
.pr-file-tree-row--dir {
2395+
.pr-files-sidebar__list > .d {
23962396
grid-template-columns: 16px 18px minmax(0, 1fr);
23972397
font-weight: 600;
23982398
}
23992399

2400-
.pr-file-tree-row__chevron,
2401-
.pr-file-tree-row__spacer,
2402-
.pr-file-tree-row__folder,
2403-
.pr-file-tree-row__file {
2400+
.pr-files-sidebar__list > .r::before,
2401+
.pr-files-sidebar__list > .r > b {
24042402
display: inline-flex;
24052403
align-items: center;
24062404
justify-content: center;
@@ -2409,43 +2407,61 @@ form {
24092407
color: #57606a;
24102408
}
24112409

2412-
.pr-file-tree-row__chevron svg {
2413-
width: 14px;
2414-
height: 14px;
2410+
.pr-files-sidebar__list > .d::before {
2411+
content: ">";
2412+
font-size: 13px;
2413+
line-height: 1;
24152414
transition: transform 0.08s;
24162415
}
24172416

2418-
.pr-file-tree-row--dir[aria-expanded="true"] .pr-file-tree-row__chevron svg {
2417+
.pr-files-sidebar__list > .d[aria-expanded="true"]::before {
24192418
transform: rotate(90deg);
24202419
}
24212420

2422-
.pr-file-tree-row__folder {
2423-
color: #54aeff;
2421+
.pr-files-sidebar__list > .f::before {
2422+
content: "";
2423+
}
24242424

2425-
svg {
2426-
width: 16px;
2427-
height: 16px;
2428-
}
2425+
.pr-files-sidebar__list > .r > b {
2426+
position: relative;
2427+
flex: 0 0 auto;
24292428
}
24302429

2431-
.pr-file-tree-row__file {
2432-
color: #57606a;
2430+
.pr-files-sidebar__list > .d > b {
2431+
width: 15px;
2432+
height: 11px;
2433+
border-radius: 2px;
2434+
background-color: #54aeff;
2435+
}
24332436

2434-
svg {
2435-
width: 15px;
2436-
height: 15px;
2437-
}
2437+
.pr-files-sidebar__list > .d > b::before {
2438+
content: "";
2439+
position: absolute;
2440+
top: -3px;
2441+
left: 1px;
2442+
width: 7px;
2443+
height: 4px;
2444+
border-radius: 2px 2px 0 0;
2445+
background-color: #54aeff;
2446+
}
2447+
2448+
.pr-files-sidebar__list > .f > b {
2449+
width: 12px;
2450+
height: 14px;
2451+
border: 1px solid #57606a;
2452+
border-radius: 2px;
2453+
box-sizing: border-box;
24382454
}
24392455

2440-
.pr-file-tree-row__name {
2456+
.pr-files-sidebar__list > .r > span {
24412457
min-width: 0;
24422458
overflow: hidden;
24432459
text-overflow: ellipsis;
24442460
white-space: nowrap;
24452461
line-height: 1.35;
24462462
}
24472463

2448-
.pr-file-link__status {
2464+
.pr-files-sidebar__list > .r > em {
24492465
display: inline-flex;
24502466
align-items: center;
24512467
justify-content: center;
@@ -2455,18 +2471,25 @@ form {
24552471
background-color: #eef3f8;
24562472
color: #57606a;
24572473
font-size: 10px;
2474+
font-style: normal;
24582475
font-weight: 700;
24592476
line-height: 1;
24602477
}
24612478

2462-
.pr-file-link__counts {
2479+
.pr-files-sidebar__list > .r > small {
24632480
display: inline-flex;
24642481
gap: 6px;
24652482
font-family: SFMono-Regular, Menlo, Monaco, Consolas, monospace;
24662483
font-size: 11px;
24672484
font-weight: 600;
24682485
}
24692486

2487+
.pr-files-sidebar__list > .r > small > b { color: #1f883d; }
2488+
.pr-files-sidebar__list > .r > small > i {
2489+
color: #cf222e;
2490+
font-style: normal;
2491+
}
2492+
24702493
.pr-files-filter-empty {
24712494
padding: 12px;
24722495
border-top: 1px solid #eef1f4;
@@ -2578,9 +2601,9 @@ form {
25782601
font-family: SFMono-Regular, Menlo, Monaco, Consolas, monospace;
25792602
}
25802603

2581-
.pr-diff__table > p.c > * { background-color: $white; }
2582-
.pr-diff__table > p.a > * { background-color: #e6ffec; }
2583-
.pr-diff__table > p.d > * { background-color: #ffebe9; }
2604+
.pr-diff__table > p.c { background-color: $white; }
2605+
.pr-diff__table > p.a { background-color: #e6ffec; }
2606+
.pr-diff__table > p.d { background-color: #ffebe9; }
25842607

25852608
.pr-diff__table > p.a > u,
25862609
.pr-diff__table > p.a > i {
@@ -2750,11 +2773,11 @@ form {
27502773
flex-direction: column;
27512774
}
27522775

2753-
.pr-file-tree-row--file {
2776+
.pr-files-sidebar__list > .f {
27542777
grid-template-columns: 16px 18px minmax(0, 1fr) 18px;
27552778
}
27562779

2757-
.pr-file-link__counts {
2780+
.pr-files-sidebar__list > .r > small {
27582781
grid-column: 3 / -1;
27592782
}
27602783
}

static/js/gitly.js

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,14 @@ function initPrFilesTree() {
5454
const clearButton = document.querySelector("[data-pr-files-filter-clear]");
5555
const countEl = document.querySelector("[data-pr-files-count]");
5656
const emptyEl = document.querySelector("[data-pr-files-filter-empty]");
57-
const rows = Array.from(tree.querySelectorAll("[data-pr-tree-row]"));
58-
const fileRows = rows.filter((row) => row.hasAttribute("data-file-path"));
57+
const rows = Array.from(tree.querySelectorAll(".r, [data-pr-tree-row]"));
58+
const fileRows = rows.filter((row) => row.hasAttribute("p") || row.hasAttribute("data-file-path"));
5959
const diffEls = Array.from(document.querySelectorAll("[data-diff-path]"));
6060
const totalFiles = fileRows.length;
6161
const collapsedDirs = new Set();
6262

6363
function pathForRow(row) {
64-
return row.getAttribute("data-file-path") || row.getAttribute("data-dir-path") || "";
64+
return row.getAttribute("p") || row.getAttribute("q") || row.getAttribute("data-file-path") || row.getAttribute("data-dir-path") || "";
6565
}
6666

6767
function addParentDirs(path, visibleDirs) {
@@ -88,16 +88,16 @@ function initPrFilesTree() {
8888
let visibleFileCount = 0;
8989

9090
for (const row of fileRows) {
91-
const path = row.getAttribute("data-file-path") || "";
91+
const path = row.getAttribute("p") || row.getAttribute("data-file-path") || "";
9292
if (query === "" || path.toLowerCase().indexOf(query) !== -1) {
9393
visibleFileCount++;
9494
addParentDirs(path, visibleDirs);
9595
}
9696
}
9797

9898
for (const row of rows) {
99-
const filePath = row.getAttribute("data-file-path");
100-
const dirPath = row.getAttribute("data-dir-path");
99+
const filePath = row.getAttribute("p") || row.getAttribute("data-file-path");
100+
const dirPath = row.getAttribute("q") || row.getAttribute("data-dir-path");
101101
let visible = true;
102102

103103
if (filePath) {
@@ -129,11 +129,11 @@ function initPrFilesTree() {
129129
}
130130

131131
for (const row of rows) {
132-
if (!row.hasAttribute("data-dir-path")) {
132+
if (!row.hasAttribute("q") && !row.hasAttribute("data-dir-path")) {
133133
continue;
134134
}
135135
row.addEventListener("click", () => {
136-
const path = row.getAttribute("data-dir-path");
136+
const path = row.getAttribute("q") || row.getAttribute("data-dir-path");
137137
if (!path) {
138138
return;
139139
}
@@ -166,6 +166,62 @@ function initPrFilesTree() {
166166
applyPrFilesFilter();
167167
}
168168

169+
function initPrReviewCommentBoxes() {
170+
const root = document.querySelector(".pr-files-diffs");
171+
if (!root) {
172+
return;
173+
}
174+
const placeholder = root.getAttribute("data-line-comment-placeholder") || "";
175+
176+
function ensureBox(row) {
177+
if (!row || !row.hasAttribute("s") || !row.hasAttribute("l")) {
178+
return null;
179+
}
180+
const next = row.nextElementSibling;
181+
if (next && next.classList.contains("m")) {
182+
return next;
183+
}
184+
const diff = row.closest("[data-diff-path]");
185+
const path = diff ? diff.getAttribute("data-diff-path") : "";
186+
const side = row.getAttribute("s") === "n" ? "new" : "old";
187+
const line = row.getAttribute("l") || "";
188+
if (!path || !line) {
189+
return null;
190+
}
191+
const wrap = document.createElement("p");
192+
wrap.className = "m";
193+
const textarea = document.createElement("textarea");
194+
textarea.name = "rc::" + path + "::" + side + "::" + line;
195+
textarea.rows = 2;
196+
if (placeholder) {
197+
textarea.placeholder = placeholder;
198+
}
199+
wrap.appendChild(textarea);
200+
row.insertAdjacentElement("afterend", wrap);
201+
return wrap;
202+
}
203+
204+
function rowFromEvent(event) {
205+
const target = event.target instanceof Element ? event.target : null;
206+
return target ? target.closest(".pr-diff__table > p[s][l]") : null;
207+
}
208+
209+
root.addEventListener("mouseover", (event) => {
210+
ensureBox(rowFromEvent(event));
211+
});
212+
root.addEventListener("focusin", (event) => {
213+
ensureBox(rowFromEvent(event));
214+
});
215+
root.addEventListener("click", (event) => {
216+
const box = ensureBox(rowFromEvent(event));
217+
const textarea = box ? box.querySelector("textarea") : null;
218+
if (textarea) {
219+
textarea.focus();
220+
}
221+
});
222+
}
223+
169224
document.addEventListener("DOMContentLoaded", () => {
170225
initPrFilesTree();
226+
initPrReviewCommentBoxes();
171227
});

0 commit comments

Comments
 (0)