Skip to content

Commit

Permalink
Shrink confirmation dialog for grouped tabs to smaller than the owner…
Browse files Browse the repository at this point in the history
… window #3136
  • Loading branch information
piroor committed May 31, 2022
1 parent 57a4a69 commit db88d8b
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 92 deletions.
91 changes: 2 additions & 89 deletions webextensions/background/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -542,24 +542,12 @@ export async function confirmToCloseTabs(tabs, { windowId, configKey, messageKey

const win = await browser.windows.get(windowId);
const listing = configs.warnOnCloseTabsWithListing ?
tabsToHTMLList(tabs, {
Dialog.tabsToHTMLList(tabs, {
maxHeight: Math.round(win.height * 0.8),
maxWidth: Math.round(win.width * 0.75)
}) :
'';

browser.runtime.onMessage.addListener(function onMessage(message, sender) {
switch (message.type) {
case Constants.kNOTIFY_CONFIRMATION_DIALOG_READY:
browser.runtime.onMessage.removeListener(onMessage);
tryRepositionDialogToCenterOfOwner({
...message,
dialogWindowId: sender.tab.windowId,
});
break;
}
});

const result = await Dialog.show(win, {
content: `
<div>${sanitizeForHTMLText(browser.i18n.getMessage(messageKey || 'warnOnCloseTabs_message', [count]))}</div>${listing}
Expand All @@ -574,28 +562,14 @@ export async function confirmToCloseTabs(tabs, { windowId, configKey, messageKey
type: 'common-dialog', // for popup
url: '/resources/blank.html', // for popup, required on Firefox ESR68
title: browser.i18n.getMessage(titleKey || 'warnOnCloseTabs_title'), // for popup
inject: {
type: Constants.kNOTIFY_CONFIRMATION_DIALOG_READY,
windowId,
},
onShownInPopup(container, { type, windowId }) {
onShownInPopup(container) {
setTimeout(() => {
// this need to be done on the next tick, to use the height of
// the box for calculation of dialog size
const style = container.querySelector('ul').style;
style.height = '0px'; // this makes the box shrinkable
style.maxHeight = 'none';
style.minHeight = '0px';
// We cannot move this window by this callback function, thus I just send
// a request to update window position.
browser.runtime.sendMessage({
type,
ownerWindowId: windowId,
availLeft: screen.availLeft,
availTop: screen.availTop,
availWidth: screen.availWidth,
availHeight: screen.availHeight,
});
}, 0);
}
});
Expand All @@ -617,67 +591,6 @@ Commands.onTabsClosing.addListener((tabIds, options = {}) => {
return confirmToCloseTabs(tabIds.map(Tab.get), options);
});

async function tryRepositionDialogToCenterOfOwner({ dialogWindowId, ownerWindowId, availLeft, availTop, availWidth, availHeight }) {
const [dialogWin, ownerWin] = await Promise.all([
browser.windows.get(dialogWindowId),
browser.windows.get(ownerWindowId),
]);
const placedOnOwner = (
dialogWin.left + dialogWin.width - (dialogWin.width / 2) < ownerWin.left &&
dialogWin.top + dialogWin.height - (dialogWin.height / 2) < ownerWin.top &&
dialogWin.left + (dialogWin.width / 2) < ownerWin.left + ownerWin.width &&
dialogWin.top + (dialogWin.height / 2) < ownerWin.top + ownerWin.height
);
const placedInsideViewArea = (
dialogWin.left >= availLeft &&
dialogWin.top >= availTop &&
dialogWin.left + dialogWin.width <= availLeft + availWidth &&
dialogWin.top + dialogWin.height <= availTop + availHeight
);
if (placedOnOwner && placedInsideViewArea)
return;

const top = ownerWin.top + Math.round((ownerWin.height - dialogWin.height) / 2);
const left = ownerWin.left + Math.round((ownerWin.width - dialogWin.width) / 2);
return browser.windows.update(dialogWin.id, {
left: Math.min(availLeft + availWidth - dialogWin.width, Math.max(availLeft, left)),
top: Math.min(availTop + availHeight - dialogWin.height, Math.max(availTop, top)),
});
}

export function tabsToHTMLList(tabs, { maxHeight, maxWidth }) {
const rootLevelOffset = tabs.map(tab => parseInt(tab.$TST.getAttribute(Constants.kLEVEL) || 0)).sort()[0];
return (
`<ul style="border: 1px inset;
display: flex;
flex-direction: column;
flex-grow: 1;
flex-shrink: 1;
margin: 0.5em 0;
min-height: 2em;
max-height: calc(${maxHeight}px - 12em /* title bar, message, checkbox, buttons, and margins */);
max-width: ${maxWidth}px;
overflow: auto;
padding: 0.5em;">` +
tabs.map(tab => `<li style="align-items: center;
display: flex;
flex-direction: row;
padding-left: calc((${tab.$TST.getAttribute(Constants.kLEVEL)} - ${rootLevelOffset}) * 0.25em);"
title="${sanitizeForHTMLText(tab.title)}"
><img style="display: flex;
max-height: 1em;
max-width: 1em;"
alt=""
src="${sanitizeForHTMLText(tab.favIconUrl || browser.runtime.getURL('resources/icons/defaultFavicon.svg'))}"
><span style="margin-left: 0.25em;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;"
>${sanitizeForHTMLText(tab.title)}</span></li>`).join('') +
`</ul>`
);
}

function reserveToClearGrantedRemovingTabs() {
const lastGranted = configs.grantedRemovingTabIds.join(',');
setTimeout(() => {
Expand Down
7 changes: 5 additions & 2 deletions webextensions/background/handle-tab-bunches.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import Tab from '/common/Tab.js';
import * as TabsGroup from './tabs-group.js';
import * as TabsOpen from './tabs-open.js';
import * as Tree from './tree.js';
import * as Background from './background.js';

function log(...args) {
internalLogger('background/handle-tab-bunches', ...args);
Expand Down Expand Up @@ -245,7 +244,11 @@ async function confirmToAutoGroupNewTabsFromOthers(tabs) {
const win = await browser.windows.get(windowId);

const listing = configs.warnOnAutoGroupNewTabsWithListing ?
Background.tabsToHTMLList(tabs, { maxRows: configs.warnOnAutoGroupNewTabsWithListingMaxRows }) :
Dialog.tabsToHTMLList(tabs, {
maxRows: configs.warnOnAutoGroupNewTabsWithListingMaxRows,
maxHeight: Math.round(win.height * 0.8),
maxWidth: Math.round(win.width * 0.75)
}) :
'';
const result = await Dialog.show(win, {
content: `
Expand Down
97 changes: 96 additions & 1 deletion webextensions/common/dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
log as internalLogger,
configs,
isMacOS,
sanitizeForHTMLText,
} from '/common/common.js';

import * as Constants from './constants.js';
Expand Down Expand Up @@ -79,9 +80,42 @@ export async function show(ownerWindow, dialogParams) {
else {
log('showDialog: show in a popup window on ', ownerWindow.id);
UserOperationBlocker.blockIn(ownerWindow.id, { throbber: false });
browser.runtime.onMessage.addListener(function onMessage(message, sender) {
switch (message.type) {
case Constants.kNOTIFY_CONFIRMATION_DIALOG_READY:
browser.runtime.onMessage.removeListener(onMessage);
tryRepositionDialogToCenterOfOwner({
...message,
dialogWindowId: sender.tab.windowId,
});
break;
}
});
const callback = dialogParams.onShownInPopup || dialogParams.onShown;
result = await RichConfirm.showInPopup(ownerWindow.id, {
...dialogParams,
onShown: dialogParams.onShownInPopup || dialogParams.onShown,
inject: {
...(dialogParams.inject || {}),
__dialog__reportScreenMessageType: Constants.kNOTIFY_CONFIRMATION_DIALOG_READY,
__dialog__ownerWindowId: ownerWindow.id,
},
onShown: [
...(Array.isArray(callback) ? callback : [callback]),
(container, { __dialog__reportScreenMessageType, __dialog__ownerWindowId }) => {
setTimeout(() => {
// We cannot move this window by this callback function, thus I just send
// a request to update window position.
browser.runtime.sendMessage({
type: __dialog__reportScreenMessageType,
ownerWindowId: __dialog__ownerWindowId,
availLeft: screen.availLeft,
availTop: screen.availTop,
availWidth: screen.availWidth,
availHeight: screen.availHeight,
});
}, 0);
},
],
onHidden(...params) {
UserOperationBlocker.unblockIn(ownerWindow.id, { throbber: false });
unblocked = true;
Expand All @@ -100,3 +134,64 @@ export async function show(ownerWindow, dialogParams) {
}
return result;
}

async function tryRepositionDialogToCenterOfOwner({ dialogWindowId, ownerWindowId, availLeft, availTop, availWidth, availHeight }) {
const [dialogWin, ownerWin] = await Promise.all([
browser.windows.get(dialogWindowId),
browser.windows.get(ownerWindowId),
]);
const placedOnOwner = (
dialogWin.left + dialogWin.width - (dialogWin.width / 2) < ownerWin.left &&
dialogWin.top + dialogWin.height - (dialogWin.height / 2) < ownerWin.top &&
dialogWin.left + (dialogWin.width / 2) < ownerWin.left + ownerWin.width &&
dialogWin.top + (dialogWin.height / 2) < ownerWin.top + ownerWin.height
);
const placedInsideViewArea = (
dialogWin.left >= availLeft &&
dialogWin.top >= availTop &&
dialogWin.left + dialogWin.width <= availLeft + availWidth &&
dialogWin.top + dialogWin.height <= availTop + availHeight
);
if (placedOnOwner && placedInsideViewArea)
return;

const top = ownerWin.top + Math.round((ownerWin.height - dialogWin.height) / 2);
const left = ownerWin.left + Math.round((ownerWin.width - dialogWin.width) / 2);
return browser.windows.update(dialogWin.id, {
left: Math.min(availLeft + availWidth - dialogWin.width, Math.max(availLeft, left)),
top: Math.min(availTop + availHeight - dialogWin.height, Math.max(availTop, top)),
});
}

export function tabsToHTMLList(tabs, { maxHeight, maxWidth }) {
const rootLevelOffset = tabs.map(tab => parseInt(tab.$TST.getAttribute(Constants.kLEVEL) || 0)).sort()[0];
return (
`<ul style="border: 1px inset;
display: flex;
flex-direction: column;
flex-grow: 1;
flex-shrink: 1;
margin: 0.5em 0;
min-height: 2em;
max-height: calc(${maxHeight}px - 12em /* title bar, message, checkbox, buttons, and margins */);
max-width: ${maxWidth}px;
overflow: auto;
padding: 0.5em;">` +
tabs.map(tab => `<li style="align-items: center;
display: flex;
flex-direction: row;
padding-left: calc((${tab.$TST.getAttribute(Constants.kLEVEL)} - ${rootLevelOffset}) * 0.25em);"
title="${sanitizeForHTMLText(tab.title)}"
><img style="display: flex;
max-height: 1em;
max-width: 1em;"
alt=""
src="${sanitizeForHTMLText(tab.favIconUrl || browser.runtime.getURL('resources/icons/defaultFavicon.svg'))}"
><span style="margin-left: 0.25em;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;"
>${sanitizeForHTMLText(tab.title)}</span></li>`).join('') +
`</ul>`
);
}

0 comments on commit db88d8b

Please sign in to comment.