feat: preview mobile review diffs (#123)
This commit is contained in:
1 parent
f662361b09
commit
6c4ce5cf48
5 files changed
+220
-3
No files matched your search
+16
-3
@@ -71,6 +71,14 @@ textarea { resize: vertical; min-height: 120px; }
|
||||
.review-sheet-header { display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap; }
|
||||
.review-sheet-body { white-space:pre-wrap; overflow-wrap:anywhere; }
|
||||
.review-file, .review-history { padding:8px 0; border-bottom:1px solid #1b2d45; overflow-wrap:anywhere; }
|
||||
.review-file-toggle { min-height:44px; width:100%; display:flex; align-items:flex-start; justify-content:space-between; gap:8px; text-align:left; }
|
||||
.review-file-toggle strong { overflow-wrap:anywhere; }
|
||||
.review-diff { overflow-x:auto; max-width:100%; margin-top:8px; white-space:pre; }
|
||||
.review-diff-line { display:block; min-width:max-content; }
|
||||
.review-diff-line.hunk { color:#93c5fd; }
|
||||
.review-diff-line.added { color:#86efac; background:rgba(34,197,94,.09); }
|
||||
.review-diff-line.removed { color:#fca5a5; background:rgba(239,68,68,.09); }
|
||||
.review-diff-note, .review-diff-empty { display:block; padding:8px; color:#fcd34d; white-space:normal; }
|
||||
.review-action { min-height:44px; }
|
||||
@media (max-width: 600px) {
|
||||
header { align-items:flex-start; }
|
||||
@@ -373,10 +381,15 @@ textarea { resize: vertical; min-height: 120px; }
|
||||
if (selectedReview !== item) return;
|
||||
qs('#review-sheet-body').textContent = detail.body || 'No description provided.';
|
||||
qs('#review-ci-state').textContent = 'CI ' + (detail.ci_state || 'unknown');
|
||||
qs('#review-files').innerHTML = (detail.files || []).length ? detail.files.map(file =>
|
||||
'<div class="review-file"><strong>' + escapeHtml(file.filename || 'Unknown file') + '</strong><div class="small">' +
|
||||
escapeHtml(file.status || 'changed') + ' · +' + Number(file.additions || 0) + ' / −' + Number(file.deletions || 0) + '</div></div>'
|
||||
qs('#review-files').innerHTML = (detail.files || []).length ? detail.files.map((file, index) =>
|
||||
createReviewController.renderDiffFile(file, index, escapeHtml)
|
||||
).join('') : '<div>No changed files reported.</div>';
|
||||
document.querySelectorAll('.review-file-toggle').forEach(button => {
|
||||
button.addEventListener('click', () => {
|
||||
const panel = document.getElementById(button.getAttribute('aria-controls'));
|
||||
if (panel) createReviewController.toggleDiff(button, panel);
|
||||
});
|
||||
});
|
||||
qs('#review-history').innerHTML = (detail.reviews || []).length ? detail.reviews.map(review =>
|
||||
'<div class="review-history"><strong>' + escapeHtml(review.user?.login || 'Reviewer') + '</strong> · ' +
|
||||
escapeHtml(review.state || 'commented') + (review.body ? '<div class="small">' + escapeHtml(review.body) + '</div>' : '') + '</div>'
|
||||
|
||||
@@ -15,6 +15,44 @@ function createReviewController({ fetchJson }) {
|
||||
return { load };
|
||||
}
|
||||
|
||||
function diffLineClass(line) {
|
||||
if (line.startsWith('@@')) return 'hunk';
|
||||
if (line.startsWith('+')) return 'added';
|
||||
if (line.startsWith('-')) return 'removed';
|
||||
return 'context';
|
||||
}
|
||||
|
||||
function renderDiffFile(file, index, escapeHtml) {
|
||||
const panelId = 'review-diff-' + index;
|
||||
let preview;
|
||||
if (file.diff_available) {
|
||||
const lines = (file.diff_lines || []).map(line =>
|
||||
'<span class="review-diff-line ' + diffLineClass(String(line)) + '">' +
|
||||
escapeHtml(String(line)) + '</span>'
|
||||
).join('');
|
||||
preview = '<pre class="review-diff" id="' + panelId + '" hidden>' + lines +
|
||||
(file.diff_truncated ? '<span class="review-diff-note">Preview truncated · open in Gitea for the full diff.</span>' : '') +
|
||||
'</pre>';
|
||||
} else {
|
||||
const message = file.diff_binary ? 'Binary file · preview unavailable.' : 'Diff preview unavailable.';
|
||||
preview = '<div class="review-diff-empty" id="' + panelId + '" hidden>' + message +
|
||||
(file.diff_truncated ? ' The response was truncated.' : '') + '</div>';
|
||||
}
|
||||
return '<div class="review-file"><button class="review-file-toggle" aria-expanded="false" aria-controls="' + panelId + '">' +
|
||||
'<strong>' + escapeHtml(file.filename || 'Unknown file') + '</strong><span class="small">' +
|
||||
escapeHtml(file.status || 'changed') + ' · +' + Number(file.additions || 0) + ' / −' +
|
||||
Number(file.deletions || 0) + '</span></button>' + preview + '</div>';
|
||||
}
|
||||
|
||||
function toggleDiff(button, panel) {
|
||||
const expanded = button.getAttribute('aria-expanded') === 'true';
|
||||
button.setAttribute('aria-expanded', String(!expanded));
|
||||
panel.hidden = expanded;
|
||||
}
|
||||
|
||||
createReviewController.renderDiffFile = renderDiffFile;
|
||||
createReviewController.toggleDiff = toggleDiff;
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = createReviewController;
|
||||
}
|
||||
Reference in new issue
Block a user