Fixed issue on Android phone with picture viewing, to able to go back to the app

This commit is contained in:
defnax 2026-08-25 18:18:36 +02:00
parent 3c7bc4bfb7
commit aac62d1268
3 changed files with 99 additions and 13 deletions

View File

@ -117,6 +117,69 @@ function isEmbeddedImageSrc(src) {
return /^data:image\//i.test(String(src).trim());
}
// Keep chat pictures inside the current page. A blank window opened here can
// strand embedded browsers such as Android WebView without a usable Back entry.
let chatImageViewer = null;
let chatImageViewerPreviousOverflow = '';
const CHAT_IMAGE_VIEWER_HISTORY_KEY = 'chatImageViewer';
function removeChatImageViewer() {
if (!chatImageViewer) return;
chatImageViewer.remove();
chatImageViewer = null;
document.body.style.overflow = chatImageViewerPreviousOverflow;
}
function closeChatImageViewer() {
if (history.state && history.state[CHAT_IMAGE_VIEWER_HISTORY_KEY]) {
history.back();
} else {
removeChatImageViewer();
}
}
window.addEventListener('popstate', () => removeChatImageViewer());
function openChatImageViewer(src) {
removeChatImageViewer();
const overlay = document.createElement('div');
overlay.className = 'chat-image-viewer';
overlay.setAttribute('role', 'dialog');
overlay.setAttribute('aria-modal', 'true');
overlay.setAttribute('aria-label', 'Image preview');
const image = document.createElement('img');
image.className = 'chat-image-viewer__image';
image.src = src;
image.alt = 'Chat image';
const closeButton = document.createElement('button');
closeButton.className = 'chat-image-viewer__close';
closeButton.type = 'button';
closeButton.setAttribute('aria-label', 'Close image preview');
closeButton.innerHTML = '×';
closeButton.onclick = (event) => {
event.stopPropagation();
closeChatImageViewer();
};
overlay.append(image, closeButton);
overlay.onclick = (event) => {
if (event.target === overlay) closeChatImageViewer();
};
overlay.onkeydown = (event) => {
if (event.key === 'Escape') closeChatImageViewer();
};
chatImageViewerPreviousOverflow = document.body.style.overflow;
document.body.style.overflow = 'hidden';
document.body.appendChild(overlay);
chatImageViewer = overlay;
history.pushState({ ...(history.state || {}), [CHAT_IMAGE_VIEWER_HISTORY_KEY]: true }, '');
closeButton.focus();
}
function renderChatMessage(rawText) {
if (!rawText) return '';
@ -159,12 +222,7 @@ function renderChatMessage(rawText) {
cursor: 'pointer',
boxShadow: '0 1px 3px rgba(0,0,0,0.1)',
},
onclick: () => {
const w = window.open('');
if (w) {
w.document.write(`<body style="margin:0;background:#0f172a;display:flex;justify-content:center;align-items:center;min-height:100vh;"><img src="${src}" style="max-width:100%;max-height:100vh;object-fit:contain;"/></body>`);
}
}
onclick: () => openChatImageViewer(src),
})
);
}
@ -198,12 +256,7 @@ function renderChatMessage(rawText) {
cursor: 'pointer',
boxShadow: '0 1px 3px rgba(0,0,0,0.1)',
},
onclick: () => {
const w = window.open('');
if (w) {
w.document.write(`<body style="margin:0;background:#0f172a;display:flex;justify-content:center;align-items:center;min-height:100vh;"><img src="${src}" style="max-width:100%;max-height:100vh;object-fit:contain;"/></body>`);
}
}
onclick: () => openChatImageViewer(src),
});
}

View File

@ -2169,3 +2169,36 @@ label.mobile-chat-attachment__option:hover {
}
}
.chat-image-viewer {
position: fixed;
inset: 0;
z-index: 1000000;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: 3.5rem 1rem 1rem;
background: rgba(15, 23, 42, 0.98);
&__image {
display: block;
max-width: 100%;
max-height: 100%;
object-fit: contain;
}
&__close {
position: absolute;
top: max(0.5rem, env(safe-area-inset-top));
right: max(0.5rem, env(safe-area-inset-right));
width: 2.75rem;
height: 2.75rem;
padding: 0;
border: 1px solid rgba(255, 255, 255, 0.5);
border-radius: 50%;
background: rgba(0, 0, 0, 0.45);
color: #fff;
font-size: 2rem;
line-height: 1;
}
}

File diff suppressed because one or more lines are too long