Add option to prompt container selection
This commit is contained in:
parent
f7e9deebda
commit
747df1c425
6 changed files with 275 additions and 5 deletions
107
src/css/select-page.css
Normal file
107
src/css/select-page.css
Normal file
|
@ -0,0 +1,107 @@
|
|||
/* General Rules and Resets */
|
||||
.title {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
main {
|
||||
background: url(/img/onboarding-4.png) no-repeat;
|
||||
background-position: 200px 0;
|
||||
background-size: 120px;
|
||||
margin-inline-start: -350px;
|
||||
padding-inline-start: 350px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 900px) {
|
||||
main {
|
||||
background: none;
|
||||
}
|
||||
|
||||
/* for a mid sized window we have enough for this but not our image */
|
||||
.title {
|
||||
background-image: url('chrome://global/skin/icons/info.svg');
|
||||
}
|
||||
}
|
||||
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
font: message-box;
|
||||
}
|
||||
|
||||
#redirect-url,
|
||||
#redirect-origin {
|
||||
font-weight: bold;
|
||||
|
||||
/* max-inline-size is needed to force this text smaller than the layout at a mid-sized window */
|
||||
max-inline-size: 40rem;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
#redirect-url {
|
||||
background: #efedf0; /* Grey 20 */
|
||||
border-radius: 2px;
|
||||
line-height: 1.5;
|
||||
padding-block-end: 0.5rem;
|
||||
padding-block-start: 0.5rem;
|
||||
padding-inline-end: 0.5rem;
|
||||
padding-inline-start: 0.5rem;
|
||||
}
|
||||
|
||||
/* stylelint-disable media-feature-name-no-unknown */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
#redirect-url {
|
||||
background: #38383d; /* Grey 70 */
|
||||
color: #eee; /* White 20 */
|
||||
}
|
||||
}
|
||||
/* stylelint-enable */
|
||||
|
||||
#redirect-url img {
|
||||
block-size: 16px;
|
||||
inline-size: 16px;
|
||||
margin-inline-end: 6px;
|
||||
offset-block-start: 3px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
dfn {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.check-label {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#redirect-identities {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 7.5px;
|
||||
}
|
||||
|
||||
#redirect-identities button {
|
||||
flex-grow: 1;
|
||||
flex-basis: 180px;
|
||||
margin: 0;
|
||||
padding: 7.5px;
|
||||
height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 7.5px;
|
||||
}
|
||||
|
||||
#redirect-identities button .primary {
|
||||
flex-grow: 2;
|
||||
flex-basis: 360px;
|
||||
}
|
||||
|
||||
#redirect-identities button img {
|
||||
position: relative;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
filter: url('/img/filters.svg#fill');
|
||||
}
|
||||
|
||||
#redirect-identities button label {
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
}
|
|
@ -56,6 +56,11 @@ window.assignManager = {
|
|||
return !!replaceTabEnabled;
|
||||
},
|
||||
|
||||
async getContainerPromptEnabled() {
|
||||
const { containerPromptEnabled } = await browser.storage.local.get("containerPromptEnabled");
|
||||
return !!containerPromptEnabled;
|
||||
},
|
||||
|
||||
getByUrlKey(siteStoreKey) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.area.get([siteStoreKey]).then((storageResponse) => {
|
||||
|
@ -258,13 +263,18 @@ window.assignManager = {
|
|||
const siteIsolatedReloadInDefault =
|
||||
await this._maybeSiteIsolatedReloadInDefault(siteSettings, tab);
|
||||
|
||||
if (!siteIsolatedReloadInDefault) {
|
||||
if (!siteSettings
|
||||
|| userContextId === siteSettings.userContextId
|
||||
|| this.storageArea.isExempted(options.url, tab.id)) {
|
||||
// The site is not associated with a container and a container is not already
|
||||
// being used to access it. In this case, we want to prompt the user to select
|
||||
// a container before continuing.
|
||||
const containerPromptEnabled = await this.storageArea.getContainerPromptEnabled();
|
||||
const promptReloadInContainer = containerPromptEnabled && !siteSettings && !userContextId;
|
||||
|
||||
if (!siteIsolatedReloadInDefault && !promptReloadInContainer) {
|
||||
if (!siteSettings || userContextId === siteSettings.userContextId || this.storageArea.isExempted(options.url, tab.id)) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
const replaceTabEnabled = await this.storageArea.getReplaceTabEnabled();
|
||||
const removeTab = backgroundLogic.NEW_TAB_PAGES.has(tab.url)
|
||||
|| (messageHandler.lastCreatedTab
|
||||
|
@ -314,7 +324,15 @@ window.assignManager = {
|
|||
}
|
||||
}
|
||||
|
||||
if (siteIsolatedReloadInDefault) {
|
||||
if (promptReloadInContainer)
|
||||
{
|
||||
this.promptReloadPageInContainer(
|
||||
options.url,
|
||||
tab.index + 1,
|
||||
tab.active,
|
||||
openTabId
|
||||
);
|
||||
} else if (siteIsolatedReloadInDefault) {
|
||||
this.reloadPageInDefaultContainer(
|
||||
options.url,
|
||||
tab.index + 1,
|
||||
|
@ -332,6 +350,7 @@ window.assignManager = {
|
|||
openTabId
|
||||
);
|
||||
}
|
||||
|
||||
this.calculateContextMenu(tab);
|
||||
|
||||
/* Removal of existing tabs:
|
||||
|
@ -732,6 +751,22 @@ window.assignManager = {
|
|||
browser.tabs.create({url, cookieStoreId, index, active, openerTabId});
|
||||
},
|
||||
|
||||
promptReloadPageInContainer(url, index, active, openerTabId = null) {
|
||||
const loadPage = browser.runtime.getURL("select-page.html");
|
||||
let confirmUrl = `${loadPage}?url=${this.encodeURLProperty(url)}`;
|
||||
return browser.tabs.create({
|
||||
url: confirmUrl,
|
||||
openerTabId,
|
||||
index,
|
||||
active
|
||||
}).then(async () => {
|
||||
// We don't want to sync this URL ever nor clutter the users history
|
||||
browser.history.deleteUrl({url: confirmUrl});
|
||||
}).catch((e) => {
|
||||
throw e;
|
||||
});
|
||||
},
|
||||
|
||||
reloadPageInContainer(url, currentUserContextId, userContextId, index, active, neverAsk = false, openerTabId = null) {
|
||||
const cookieStoreId = backgroundLogic.cookieStoreId(userContextId);
|
||||
const loadPage = browser.runtime.getURL("confirm-page.html");
|
||||
|
|
|
@ -53,6 +53,11 @@ async function enableDisableReplaceTab() {
|
|||
await browser.storage.local.set({replaceTabEnabled: !!checkbox.checked});
|
||||
}
|
||||
|
||||
async function enableDisableContainerPrompt() {
|
||||
const checkbox = document.querySelector("#containerPromptCheck");
|
||||
await browser.storage.local.set({containerPromptEnabled: !!checkbox.checked});
|
||||
}
|
||||
|
||||
async function changeTheme(event) {
|
||||
const theme = event.currentTarget;
|
||||
await browser.storage.local.set({currentTheme: theme.value});
|
||||
|
@ -62,10 +67,12 @@ async function changeTheme(event) {
|
|||
async function setupOptions() {
|
||||
const { syncEnabled } = await browser.storage.local.get("syncEnabled");
|
||||
const { replaceTabEnabled } = await browser.storage.local.get("replaceTabEnabled");
|
||||
const { containerPromptEnabled } = await browser.storage.local.get("containerPromptEnabled");
|
||||
const { currentThemeId } = await browser.storage.local.get("currentThemeId");
|
||||
|
||||
document.querySelector("#syncCheck").checked = !!syncEnabled;
|
||||
document.querySelector("#replaceTabCheck").checked = !!replaceTabEnabled;
|
||||
document.querySelector("#containerPromptCheck").checked = !!containerPromptEnabled;
|
||||
document.querySelector("#changeTheme").selectedIndex = currentThemeId;
|
||||
setupContainerShortcutSelects();
|
||||
}
|
||||
|
@ -123,6 +130,7 @@ browser.permissions.onRemoved.addListener(resetPermissionsUi);
|
|||
document.addEventListener("DOMContentLoaded", setupOptions);
|
||||
document.querySelector("#syncCheck").addEventListener( "change", enableDisableSync);
|
||||
document.querySelector("#replaceTabCheck").addEventListener( "change", enableDisableReplaceTab);
|
||||
document.querySelector("#containerPromptCheck").addEventListener( "change", enableDisableContainerPrompt);
|
||||
document.querySelector("#changeTheme").addEventListener( "change", changeTheme);
|
||||
|
||||
maybeShowPermissionsWarningIcon();
|
||||
|
|
83
src/js/select-page.js
Normal file
83
src/js/select-page.js
Normal file
|
@ -0,0 +1,83 @@
|
|||
async function load() {
|
||||
const searchParams = new URL(window.location).searchParams;
|
||||
const redirectUrl = searchParams.get("url");
|
||||
const redirectUrlElement = document.getElementById("redirect-url");
|
||||
redirectUrlElement.textContent = redirectUrl;
|
||||
appendFavicon(redirectUrl, redirectUrlElement);
|
||||
|
||||
const identities = await browser.contextualIdentities.query({});
|
||||
const redirectFormElement = document.getElementById("redirect-identities");
|
||||
|
||||
identities.forEach(identity => {
|
||||
const cookieStoreId = identity.cookieStoreId;
|
||||
var containerButtonElement = document.createElement("button");
|
||||
containerButtonElement.classList.add("button");
|
||||
containerButtonElement.id = "container-" + identity.name;
|
||||
containerButtonElement.setAttribute("container-id", cookieStoreId);
|
||||
containerButtonElement.addEventListener("click", e => {
|
||||
e.preventDefault();
|
||||
selectContainer(redirectUrl, identity)
|
||||
})
|
||||
var containerIconElement = document.createElement("img");
|
||||
containerIconElement.src = identity.iconUrl;
|
||||
containerIconElement.alt = identity.icon;
|
||||
containerIconElement.style.fill = identity.colorCode;
|
||||
var containerLabelElement = document.createElement("label");
|
||||
containerLabelElement.textContent = identity.name;
|
||||
containerButtonElement.appendChild(containerIconElement);
|
||||
containerButtonElement.appendChild(containerLabelElement);
|
||||
redirectFormElement.appendChild(containerButtonElement);
|
||||
})
|
||||
|
||||
document.querySelectorAll("[data-message-id]").forEach(el => {
|
||||
const elementData = el.dataset;
|
||||
el.textContent = browser.i18n.getMessage(elementData.messageId);
|
||||
});
|
||||
}
|
||||
|
||||
function appendFavicon(pageUrl, redirectUrlElement) {
|
||||
const origin = new URL(pageUrl).origin;
|
||||
const favIconElement = Utils.createFavIconElement(`${origin}/favicon.ico`);
|
||||
|
||||
redirectUrlElement.prepend(favIconElement);
|
||||
}
|
||||
|
||||
function getCurrentTab() {
|
||||
return browser.tabs.query({
|
||||
active: true,
|
||||
windowId: browser.windows.WINDOW_ID_CURRENT
|
||||
});
|
||||
}
|
||||
|
||||
load();
|
||||
|
||||
function selectContainer(redirectUrl, identity){
|
||||
const neverAsk = document.getElementById("never-ask").checked;
|
||||
if (neverAsk) {
|
||||
assignContainer(redirectUrl, identity);
|
||||
}
|
||||
openInContainer(redirectUrl, identity.cookieStoreId);
|
||||
}
|
||||
|
||||
async function openInContainer(redirectUrl, cookieStoreId) {
|
||||
const tab = await getCurrentTab();
|
||||
await browser.tabs.create({
|
||||
index: tab[0].index + 1,
|
||||
cookieStoreId,
|
||||
url: redirectUrl
|
||||
});
|
||||
if (tab.length > 0) {
|
||||
browser.tabs.remove(tab[0].id);
|
||||
}
|
||||
}
|
||||
|
||||
async function assignContainer(redirectUrl, identity) {
|
||||
const currentTab = await Utils.currentTab();
|
||||
const assignedUserContextId = Utils.userContextId(identity.cookieStoreId);
|
||||
await Utils.setOrRemoveAssignment(
|
||||
null,
|
||||
redirectUrl,
|
||||
assignedUserContextId,
|
||||
false
|
||||
);
|
||||
}
|
|
@ -57,6 +57,11 @@
|
|||
<span class="bold" data-i18n-message-id="replaceTab"></span>
|
||||
</label>
|
||||
<p><em data-i18n-message-id="replaceTabDescription"></em></p>
|
||||
<label>
|
||||
<input type="checkbox" id="containerPromptCheck">
|
||||
<span class="bold" data-i18n-message-id="containerPrompt"></span>
|
||||
</label>
|
||||
<p><em data-i18n-message-id="containerPromptDescription"></em></p>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
|
|
32
src/select-page.html
Normal file
32
src/select-page.html
Normal file
|
@ -0,0 +1,32 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
<title data-i18n-message-id="confirmNavigationTitle"></title>
|
||||
<link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="chrome://browser/skin/aboutNetError.css" type="text/css" media="all" />
|
||||
<link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="chrome://global/skin/aboutNetError.css" type="text/css" media="all" />
|
||||
<script type="text/javascript" src="./js/i18n.js"></script>
|
||||
<link rel="stylesheet" href="/css/select-page.css" />
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<div class="title">
|
||||
<h1 class="title-text" data-i18n-message-id="whichContainerDoYouWantToUse"></h1>
|
||||
</div>
|
||||
<form id="redirect-form">
|
||||
<p data-message-id="noAssociatedContainer"></p>
|
||||
<div id="redirect-url"></div>
|
||||
<p data-i18n-message-id="whichContainerDoYouWantToOpen"></p>
|
||||
<br />
|
||||
<br />
|
||||
<label for="never-ask" class="check-label">
|
||||
<input id="never-ask" type="checkbox" />
|
||||
<span data-i18n-message-id="rememberMyDecision"></span>
|
||||
</label>
|
||||
<br />
|
||||
<div id="redirect-identities"></div>
|
||||
</form>
|
||||
</main>
|
||||
<script src="js/utils.js"></script>
|
||||
<script src="js/select-page.js"></script>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Reference in a new issue