fix: route popup positioning on small screens + tap-to-copy

Right-align path popup and cap max-width to viewport to prevent
overflow on narrow screens (same approach as DM route popup fix).
Add tap-to-copy on route entries — copies path in comma-separated
format (e.g. 5E,32,0D,8C) to clipboard with visual feedback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
MarekWo
2026-04-12 20:53:54 +02:00
parent acec9e92cf
commit f7f5beb8b8
3 changed files with 45 additions and 11 deletions

View File

@@ -780,11 +780,6 @@ main {
position: relative;
}
.dm-route-link > .path-popup {
left: auto;
right: 0;
}
.dm-delivery-popup {
position: absolute;
bottom: 100%;
@@ -1444,7 +1439,8 @@ main {
.path-popup {
position: absolute;
bottom: 100%;
left: 0;
right: 0;
left: auto;
background-color: #333;
color: #fff;
padding: 0.4rem 0.6rem;
@@ -1456,13 +1452,18 @@ main {
margin-bottom: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
min-width: 180px;
max-width: 320px;
max-width: min(320px, calc(100vw - 1.5rem));
}
.path-popup .path-entry {
padding: 0.15rem 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.15);
word-break: break-all;
cursor: pointer;
}
.path-popup .path-entry:active {
opacity: 0.6;
}
.path-popup .path-entry:last-child {

View File

@@ -1504,7 +1504,6 @@ function showPathsPopup(element, encodedPaths) {
const popup = document.createElement('div');
popup.className = 'path-popup';
let html = '';
paths.forEach((p, i) => {
const pChunkLen = (p.hash_size || 1) * 2;
const segments = [];
@@ -1514,15 +1513,34 @@ function showPathsPopup(element, encodedPaths) {
}
}
const fullRoute = segments.join(' \u2192 ');
const commaRoute = segments.join(',');
const snr = p.snr !== null && p.snr !== undefined ? `${p.snr.toFixed(1)} dB` : '?';
const hops = segments.length;
html += `<div class="path-entry">${fullRoute}<span class="path-detail">SNR: ${snr} | Hops: ${hops}</span></div>`;
const entry = document.createElement('div');
entry.className = 'path-entry';
entry.innerHTML = `${fullRoute}<span class="path-detail">SNR: ${snr} | Hops: ${hops}</span>`;
entry.title = 'Tap to copy route';
entry.addEventListener('click', (e) => {
e.stopPropagation();
navigator.clipboard.writeText(commaRoute).then(() => {
const orig = entry.innerHTML;
entry.innerHTML = '<span style="opacity:0.8">Copied!</span>';
setTimeout(() => { entry.innerHTML = orig; }, 1000);
});
});
popup.appendChild(entry);
});
popup.innerHTML = html;
element.style.position = 'relative';
element.appendChild(popup);
// Adjust if popup overflows viewport
const rect = popup.getBoundingClientRect();
if (rect.left < 4) {
popup.style.right = 'auto';
popup.style.left = '0';
}
// Auto-dismiss after 8 seconds or on outside tap
const dismiss = () => popup.remove();
setTimeout(dismiss, 8000);

View File

@@ -1455,10 +1455,25 @@ function showDmRoutePopup(element, hexPath, hashSize) {
const segments = segmentHexPath(hexPath, hashSize || 1);
const fullRoute = segments.join(' \u2192 ');
const commaRoute = segments.join(',');
const popup = document.createElement('div');
popup.className = 'path-popup';
popup.innerHTML = `<div class="path-entry">${fullRoute}<span class="path-detail">Hops: ${segments.length}</span></div>`;
const entry = document.createElement('div');
entry.className = 'path-entry';
entry.innerHTML = `${fullRoute}<span class="path-detail">Hops: ${segments.length}</span>`;
entry.title = 'Tap to copy route';
entry.addEventListener('click', (e) => {
e.stopPropagation();
navigator.clipboard.writeText(commaRoute).then(() => {
const orig = entry.innerHTML;
entry.innerHTML = '<span style="opacity:0.8">Copied!</span>';
setTimeout(() => { entry.innerHTML = orig; }, 1000);
});
});
popup.appendChild(entry);
element.style.position = 'relative';
element.appendChild(popup);