feat(telemirror): implement custom confirmation dialog in telemirror modal

This commit is contained in:
Sarto
2026-05-05 13:51:53 +03:30
parent b26bf2a1ee
commit 913b8c4dcb
2 changed files with 78 additions and 9 deletions
+41
View File
@@ -1311,6 +1311,34 @@
a permanent broken-image icon. */
.tm-photo-failed { display: none }
/* Confirm dialog rendered inside the telemirror modal so it sits
on top of the drawer / backdrop / posts at the right stacking. */
.tm-confirm-overlay {
position: absolute; inset: 0;
z-index: 10;
display: flex; align-items: center; justify-content: center;
padding: 16px;
background: rgba(0,0,0,.55);
animation: tm-fade-in .15s ease
}
@keyframes tm-fade-in { from { opacity: 0 } to { opacity: 1 } }
.tm-confirm-box {
max-width: 380px; width: 100%;
background: var(--bg-elevated, var(--bg));
border: 1px solid var(--border);
border-radius: 14px;
padding: 18px 20px 14px;
box-shadow: 0 12px 32px rgba(0,0,0,.4)
}
.tm-confirm-msg {
margin: 0 0 14px;
font-size: 13px; line-height: 1.7;
color: var(--text)
}
.tm-confirm-actions {
display: flex; gap: 8px; justify-content: flex-end
}
/* First-visit hint — points the user at the channel list. */
.tm-first-hint {
margin: auto;
@@ -6608,6 +6636,19 @@
// of those from the close-confirmation dialog.
window.handleAndroidBack = async function () {
if (closeMediaLightbox()) return;
// Telemirror has its own full-screen modal (.tm-modal, not
// .modal-overlay). Drawer first, then modal, then anything else.
var tmModal = document.getElementById('telemirrorModal');
if (tmModal && tmModal.classList.contains('active')) {
var tmSb = document.getElementById('tmSidebar');
if (tmSb && tmSb.classList.contains('open')) {
tmSb.classList.remove('open');
return;
}
if (typeof closeTelemirror === 'function') closeTelemirror();
else tmModal.classList.remove('active');
return;
}
var openModal = document.querySelector('.modal-overlay.active');
if (openModal) { openModal.classList.remove('active'); return; }
if (mobileQuery.matches && document.getElementById('app').classList.contains('chat-open')) {
+37 -9
View File
@@ -257,20 +257,48 @@
var msg = (tmI18n('telemirror_refresh_warn',
'You refreshed this channel {n} sec ago. Refreshing too often can hit a rate limit and stop working for a while. Refresh anyway?')
).replace('{n}', ageSec);
// Reuse the main app's themed confirm dialog if available.
var ok;
if (typeof showConfirmDialog === 'function') {
ok = await showConfirmDialog(msg,
tmI18n('telemirror_refresh_yes', 'Refresh'),
tmI18n('cancel', 'Cancel'));
} else {
ok = window.confirm(msg);
}
var ok = await tmConfirm(msg,
tmI18n('telemirror_refresh_yes', 'Refresh'),
tmI18n('cancel', 'Cancel'));
if (!ok) return;
}
tmSelect(tmActive, { refresh: true });
};
// tmConfirm — a Promise-based yes/no dialog that mounts INSIDE the
// telemirror modal so it sits above the drawer/backdrop. The main
// app's showConfirmDialog appends to <body> and lives at a lower
// z-index, so it ended up hidden behind our z:9000 modal.
function tmConfirm(message, yesText, noText) {
return new Promise(function (resolve) {
var modal = document.getElementById('telemirrorModal');
if (!modal) { resolve(window.confirm(message)); return; }
var overlay = document.createElement('div');
overlay.className = 'tm-confirm-overlay';
overlay.innerHTML =
'<div class="tm-confirm-box">'
+ '<p class="tm-confirm-msg"></p>'
+ '<div class="tm-confirm-actions">'
+ '<button class="btn btn-flat" data-tm-no></button>'
+ '<button class="btn btn-primary" data-tm-yes></button>'
+ '</div>'
+ '</div>';
overlay.querySelector('.tm-confirm-msg').textContent = message;
overlay.querySelector('[data-tm-yes]').textContent = yesText || tmI18n('ok', 'OK');
overlay.querySelector('[data-tm-no]').textContent = noText || tmI18n('cancel', 'Cancel');
var done = function (val) {
if (overlay.parentNode) overlay.parentNode.removeChild(overlay);
resolve(val);
};
overlay.addEventListener('click', function (e) {
if (e.target === overlay) done(false);
});
overlay.querySelector('[data-tm-no]').addEventListener('click', function () { done(false); });
overlay.querySelector('[data-tm-yes]').addEventListener('click', function () { done(true); });
modal.appendChild(overlay);
});
}
function tmRenderTopbar(channel, username) {
var name = (channel && channel.title) || username;
var sub = '';