fix: keep mobile review handoff popup-safe (#143)
This commit is contained in:
1 parent
54638d2686
commit
b51542363c
3 files changed
+99
-34
No files matched your search
+41
-16
@@ -87,6 +87,8 @@ textarea { resize: vertical; min-height: 120px; }
|
||||
.review-feedback select { min-height:44px; padding:8px; border-radius:8px; border:1px solid #1f3a5f; background:#0b1526; color:#e5e7eb; }
|
||||
.review-handoff { position:sticky; bottom:0; z-index:3; display:grid; gap:8px; padding:10px 4px; background:rgba(11,21,38,.98); border-top:1px solid #2a496e; }
|
||||
.review-handoff button { min-height:44px; }
|
||||
.review-handoff-link { min-height:44px; display:flex; align-items:center; justify-content:center; border:1px solid #60a5fa; border-radius:8px; color:#bfdbfe; font-weight:700; text-decoration:none; }
|
||||
.review-handoff-link[hidden] { display:none; }
|
||||
.review-copy-fallback { min-height:140px; }
|
||||
.review-progress-actions { position:sticky; bottom:0; z-index:2; display:flex; align-items:center; justify-content:space-between; gap:10px; margin:8px -4px 0; padding:10px 4px; background:rgba(11,21,38,.96); border-top:1px solid #2a496e; }
|
||||
.review-progress-actions button { min-height:44px; max-width:100%; }
|
||||
@@ -264,6 +266,7 @@ textarea { resize: vertical; min-height: 120px; }
|
||||
<button id="copy-review-feedback">Copy feedback & continue in Gitea</button>
|
||||
<span class="small" id="review-handoff-status" aria-live="polite"></span>
|
||||
<textarea class="review-copy-fallback" id="review-copy-fallback" readonly hidden aria-label="Feedback to copy manually"></textarea>
|
||||
<a class="review-handoff-link" id="review-handoff-link" target="_blank" rel="noopener noreferrer" hidden>Continue to Gitea</a>
|
||||
</div>
|
||||
</section>
|
||||
<h2>Review history</h2>
|
||||
@@ -323,6 +326,7 @@ textarea { resize: vertical; min-height: 120px; }
|
||||
let reviewFiles = [];
|
||||
let bulkConfirmationPending = false;
|
||||
let bulkMarkPending = false;
|
||||
let reviewHandoffPending = false;
|
||||
|
||||
async function fetchReviewJson(url, options) {
|
||||
const response = await fetch(url, options);
|
||||
@@ -533,6 +537,8 @@ textarea { resize: vertical; min-height: 120px; }
|
||||
qs('#review-summary').value = '';
|
||||
qs('#review-copy-fallback').hidden = true;
|
||||
qs('#review-copy-fallback').value = '';
|
||||
qs('#review-handoff-link').hidden = true;
|
||||
qs('#review-handoff-link').href = item.url;
|
||||
qs('#review-handoff-status').textContent = '';
|
||||
draft = null;
|
||||
reviewFiles = [];
|
||||
@@ -735,24 +741,43 @@ textarea { resize: vertical; min-height: 120px; }
|
||||
qs('#review-summary').addEventListener('input', event => draft?.setSummary(event.target.value));
|
||||
qs('#review-decision').addEventListener('change', event => draft?.setDecision(event.target.value));
|
||||
qs('#copy-review-feedback').addEventListener('click', async () => {
|
||||
if (!draft || !selectedReview) return;
|
||||
if (!draft || !selectedReview || reviewHandoffPending) return;
|
||||
reviewHandoffPending = true;
|
||||
qs('#copy-review-feedback').disabled = true;
|
||||
const fallback = qs('#review-copy-fallback');
|
||||
const directLink = qs('#review-handoff-link');
|
||||
fallback.hidden = true;
|
||||
const copied = await createReviewController.copyAndContinue({
|
||||
text: createReviewController.formatFeedback(draft.snapshot(), reviewFiles),
|
||||
url: selectedReview.url,
|
||||
copy: text => navigator.clipboard.writeText(text),
|
||||
open: url => window.open(url, '_blank', 'noopener,noreferrer'),
|
||||
fallback: text => {
|
||||
fallback.value = text;
|
||||
fallback.hidden = false;
|
||||
fallback.focus();
|
||||
fallback.select();
|
||||
},
|
||||
});
|
||||
qs('#review-handoff-status').textContent = copied ?
|
||||
'Feedback copied. Opening Gitea…' :
|
||||
'Clipboard unavailable. Copy the selected feedback, then use Open in Gitea.';
|
||||
directLink.hidden = true;
|
||||
let handoffWindow = null;
|
||||
try {
|
||||
const result = await createReviewController.copyAndContinue({
|
||||
text: createReviewController.formatFeedback(draft.snapshot(), reviewFiles),
|
||||
url: selectedReview.url,
|
||||
copy: text => navigator.clipboard.writeText(text),
|
||||
open: () => {
|
||||
handoffWindow = window.open('about:blank', '_blank');
|
||||
if (handoffWindow) handoffWindow.opener = null;
|
||||
return handoffWindow;
|
||||
},
|
||||
fallback: text => {
|
||||
fallback.value = text;
|
||||
fallback.hidden = false;
|
||||
fallback.focus();
|
||||
fallback.select();
|
||||
},
|
||||
});
|
||||
if (result.opened) {
|
||||
qs('#review-handoff-status').textContent = 'Feedback copied. Gitea opened in a new tab.';
|
||||
} else {
|
||||
directLink.hidden = false;
|
||||
qs('#review-handoff-status').textContent = result.copied ?
|
||||
'Feedback copied. Your browser blocked the new tab; continue with the link below.' :
|
||||
'Clipboard unavailable. Copy the selected feedback, then continue to Gitea.';
|
||||
}
|
||||
} finally {
|
||||
reviewHandoffPending = false;
|
||||
qs('#copy-review-feedback').disabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
const contextPoller = createContextPoller({
|
||||
|
||||
@@ -166,14 +166,20 @@ function formatFeedback(draft, files) {
|
||||
}
|
||||
|
||||
async function copyAndContinue({ text, url, copy, open, fallback }) {
|
||||
const destination = open();
|
||||
try {
|
||||
await copy(text);
|
||||
} catch (error) {
|
||||
destination?.close?.();
|
||||
fallback(text);
|
||||
return false;
|
||||
return { copied: false, opened: false };
|
||||
}
|
||||
open(url);
|
||||
return true;
|
||||
if (!destination) {
|
||||
fallback(text);
|
||||
return { copied: true, opened: false };
|
||||
}
|
||||
destination.location.href = url;
|
||||
return { copied: true, opened: true };
|
||||
}
|
||||
|
||||
createReviewController.renderDiffFile = renderDiffFile;
|
||||
|
||||
Reference in new issue
Block a user