WIP context menu for Alt+Shift+Click #518
This commit is contained in:
parent
8f64918638
commit
2a4891846a
7 changed files with 321 additions and 103 deletions
|
@ -408,6 +408,15 @@ const messageHandler = {
|
||||||
let response;
|
let response;
|
||||||
|
|
||||||
switch (m.method) {
|
switch (m.method) {
|
||||||
|
case "getContainers":
|
||||||
|
response = browser.contextualIdentities.query({});
|
||||||
|
break;
|
||||||
|
case "openTab":
|
||||||
|
response = browser.tabs.create({
|
||||||
|
url: m.url,
|
||||||
|
cookieStoreId: m.cookieStoreId
|
||||||
|
});
|
||||||
|
break;
|
||||||
case "deleteContainer":
|
case "deleteContainer":
|
||||||
response = backgroundLogic.deleteContainer(m.message.userContextId);
|
response = backgroundLogic.deleteContainer(m.message.userContextId);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -20,3 +20,67 @@
|
||||||
inline-size: 16px;
|
inline-size: 16px;
|
||||||
margin-inline-end: 3px;
|
margin-inline-end: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#containers-menu {
|
||||||
|
background: #fcfcfc;
|
||||||
|
border: 1px solid #979797;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: 3px 3px 5px #91919166;
|
||||||
|
font-family: Roboto, Noto, "San Francisco", Ubuntu, "Segoe UI", "Fira Sans", message-box, Arial, sans-serif;
|
||||||
|
inline-size: 7rem;
|
||||||
|
position: absolute;
|
||||||
|
padding: 0;
|
||||||
|
z-index: 9999999;
|
||||||
|
/* This is the area we allow users to move away from the menu without it closing
|
||||||
|
*/
|
||||||
|
margin: 4px;
|
||||||
|
-moz-user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#containers-menu > li:first-of-type {
|
||||||
|
border-radius: 3px 3px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#containers-menu > li:last-of-type {
|
||||||
|
border: none;
|
||||||
|
border-radius: 0 0 3px 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-theme#containers-menu {
|
||||||
|
background: #2b2f38;
|
||||||
|
}
|
||||||
|
|
||||||
|
#containers-menu > li {
|
||||||
|
align-items: center;
|
||||||
|
border-block-end: 1px solid #979797;
|
||||||
|
color: #434343;
|
||||||
|
display: flex;
|
||||||
|
margin: 0;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#containers-menu > li > span {
|
||||||
|
flex: 1;
|
||||||
|
mask-image: linear-gradient(to left, transparent, black 1em);
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-theme#containers-menu li {
|
||||||
|
color: #92959b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#containers-menu li:hover,
|
||||||
|
#containers-menu li:focus {
|
||||||
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#containers-menu > li > .usercontext-icon {
|
||||||
|
background-size: 16px;
|
||||||
|
flex: 0 0 16px;
|
||||||
|
margin-inline-end: 6px;
|
||||||
|
max-block-size: 16px;
|
||||||
|
min-block-size: 16px;
|
||||||
|
}
|
||||||
|
|
|
@ -64,95 +64,6 @@ table {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Color and icon helpers */
|
|
||||||
[data-identity-color="blue"] {
|
|
||||||
--identity-tab-color: #37adff;
|
|
||||||
--identity-icon-color: #37adff;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-identity-color="turquoise"] {
|
|
||||||
--identity-tab-color: #00c79a;
|
|
||||||
--identity-icon-color: #00c79a;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-identity-color="green"] {
|
|
||||||
--identity-tab-color: #51cd00;
|
|
||||||
--identity-icon-color: #51cd00;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-identity-color="yellow"] {
|
|
||||||
--identity-tab-color: #ffcb00;
|
|
||||||
--identity-icon-color: #ffcb00;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-identity-color="orange"] {
|
|
||||||
--identity-tab-color: #ff9f00;
|
|
||||||
--identity-icon-color: #ff9f00;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-identity-color="red"] {
|
|
||||||
--identity-tab-color: #ff613d;
|
|
||||||
--identity-icon-color: #ff613d;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-identity-color="pink"] {
|
|
||||||
--identity-tab-color: #ff4bda;
|
|
||||||
--identity-icon-color: #ff4bda;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-identity-color="purple"] {
|
|
||||||
--identity-tab-color: #af51f5;
|
|
||||||
--identity-icon-color: #af51f5;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-identity-icon="fingerprint"] {
|
|
||||||
--identity-icon: url("/img/usercontext.svg#fingerprint");
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-identity-icon="briefcase"] {
|
|
||||||
--identity-icon: url("/img/usercontext.svg#briefcase");
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-identity-icon="dollar"] {
|
|
||||||
--identity-icon: url("/img/usercontext.svg#dollar");
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-identity-icon="cart"] {
|
|
||||||
--identity-icon: url("/img/usercontext.svg#cart");
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-identity-icon="circle"] {
|
|
||||||
--identity-icon: url("/img/usercontext.svg#circle");
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-identity-icon="food"] {
|
|
||||||
--identity-icon: url("/img/usercontext.svg#food");
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-identity-icon="gift"] {
|
|
||||||
--identity-icon: url("/img/usercontext.svg#gift");
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-identity-icon="vacation"] {
|
|
||||||
--identity-icon: url("/img/usercontext.svg#vacation");
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-identity-icon="fruit"] {
|
|
||||||
--identity-icon: url("/img/usercontext.svg#fruit");
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-identity-icon="pet"] {
|
|
||||||
--identity-icon: url("/img/usercontext.svg#pet");
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-identity-icon="tree"] {
|
|
||||||
--identity-icon: url("/img/usercontext.svg#tree");
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-identity-icon="chill"] {
|
|
||||||
--identity-icon: url("/img/usercontext.svg#chill");
|
|
||||||
}
|
|
||||||
|
|
||||||
#current-tab [data-identity-icon="default-tab"] {
|
#current-tab [data-identity-icon="default-tab"] {
|
||||||
background: center center no-repeat url("/img/blank-tab.svg");
|
background: center center no-repeat url("/img/blank-tab.svg");
|
||||||
fill: currentColor;
|
fill: currentColor;
|
||||||
|
@ -486,18 +397,6 @@ span ~ .panel-header-text {
|
||||||
flex: 0 0 48px;
|
flex: 0 0 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* .userContext-icon is used natively, Bug 1333811 was raised to fix */
|
|
||||||
.usercontext-icon {
|
|
||||||
background-image: var(--identity-icon);
|
|
||||||
background-position: center center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 20px 20px;
|
|
||||||
block-size: 48px;
|
|
||||||
fill: var(--identity-icon-color);
|
|
||||||
filter: url('/img/filters.svg#fill');
|
|
||||||
flex: 0 0 48px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-panel-row:hover .clickable .usercontext-icon,
|
.container-panel-row:hover .clickable .usercontext-icon,
|
||||||
.container-panel-row:focus .clickable .usercontext-icon {
|
.container-panel-row:focus .clickable .usercontext-icon {
|
||||||
background-image: url('/img/container-newtab.svg');
|
background-image: url('/img/container-newtab.svg');
|
||||||
|
|
100
webextension/css/user-context.css
Normal file
100
webextension/css/user-context.css
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
/* Color and icon helpers */
|
||||||
|
[data-identity-color="blue"] {
|
||||||
|
--identity-tab-color: #37adff;
|
||||||
|
--identity-icon-color: #37adff;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-identity-color="turquoise"] {
|
||||||
|
--identity-tab-color: #00c79a;
|
||||||
|
--identity-icon-color: #00c79a;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-identity-color="green"] {
|
||||||
|
--identity-tab-color: #51cd00;
|
||||||
|
--identity-icon-color: #51cd00;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-identity-color="yellow"] {
|
||||||
|
--identity-tab-color: #ffcb00;
|
||||||
|
--identity-icon-color: #ffcb00;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-identity-color="orange"] {
|
||||||
|
--identity-tab-color: #ff9f00;
|
||||||
|
--identity-icon-color: #ff9f00;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-identity-color="red"] {
|
||||||
|
--identity-tab-color: #ff613d;
|
||||||
|
--identity-icon-color: #ff613d;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-identity-color="pink"] {
|
||||||
|
--identity-tab-color: #ff4bda;
|
||||||
|
--identity-icon-color: #ff4bda;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-identity-color="purple"] {
|
||||||
|
--identity-tab-color: #af51f5;
|
||||||
|
--identity-icon-color: #af51f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-identity-icon="fingerprint"] {
|
||||||
|
--identity-icon: url("/img/usercontext.svg#fingerprint");
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-identity-icon="briefcase"] {
|
||||||
|
--identity-icon: url("/img/usercontext.svg#briefcase");
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-identity-icon="dollar"] {
|
||||||
|
--identity-icon: url("/img/usercontext.svg#dollar");
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-identity-icon="cart"] {
|
||||||
|
--identity-icon: url("/img/usercontext.svg#cart");
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-identity-icon="circle"] {
|
||||||
|
--identity-icon: url("/img/usercontext.svg#circle");
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-identity-icon="food"] {
|
||||||
|
--identity-icon: url("/img/usercontext.svg#food");
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-identity-icon="gift"] {
|
||||||
|
--identity-icon: url("/img/usercontext.svg#gift");
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-identity-icon="vacation"] {
|
||||||
|
--identity-icon: url("/img/usercontext.svg#vacation");
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-identity-icon="fruit"] {
|
||||||
|
--identity-icon: url("/img/usercontext.svg#fruit");
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-identity-icon="pet"] {
|
||||||
|
--identity-icon: url("/img/usercontext.svg#pet");
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-identity-icon="tree"] {
|
||||||
|
--identity-icon: url("/img/usercontext.svg#tree");
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-identity-icon="chill"] {
|
||||||
|
--identity-icon: url("/img/usercontext.svg#chill");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .userContext-icon is used natively, Bug 1333811 was raised to fix */
|
||||||
|
.usercontext-icon {
|
||||||
|
background-image: var(--identity-icon);
|
||||||
|
background-position: center center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 20px 20px;
|
||||||
|
block-size: 48px;
|
||||||
|
fill: var(--identity-icon-color);
|
||||||
|
filter: url('/img/filters.svg#fill');
|
||||||
|
flex: 0 0 48px;
|
||||||
|
}
|
|
@ -51,3 +51,146 @@ async function addMessage(message) {
|
||||||
browser.runtime.onMessage.addListener((message) => {
|
browser.runtime.onMessage.addListener((message) => {
|
||||||
addMessage(message);
|
addMessage(message);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const menuClickHandler = {
|
||||||
|
menuElement: null,
|
||||||
|
lastUrl: null,
|
||||||
|
linkSelector:"a[href]",
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.createMenu();
|
||||||
|
|
||||||
|
document.addEventListener("keydown", this);
|
||||||
|
document.addEventListener("click", this);
|
||||||
|
},
|
||||||
|
|
||||||
|
handleEvent(e) {
|
||||||
|
switch(e.type) {
|
||||||
|
case "keydown":
|
||||||
|
if (this.isMenuOpen()) {
|
||||||
|
if (e.key === "Escape") {
|
||||||
|
this.menuClose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (e.altKey && (e.shiftKey || e.key === "Shift")) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
this.addOpenListeners();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "keyup":
|
||||||
|
if (e.altKey && (e.shiftKey || e.key === "Shift")) {
|
||||||
|
this.removeOpenListeners();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "click":
|
||||||
|
if (this.isMenuOpen() &&
|
||||||
|
(e.target.closest(this.linkSelector) || e.target.matches(this.linkSelector))) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
} else {
|
||||||
|
this.menuClose();
|
||||||
|
}
|
||||||
|
this.removeOpenListeners();
|
||||||
|
break;
|
||||||
|
case "mousedown":
|
||||||
|
if (this.isMenuOpen()) {
|
||||||
|
if (!e.target.closest("#containers-menu")) {
|
||||||
|
this.menuClose();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.target.closest(this.linkSelector) ||
|
||||||
|
e.target.matches(this.linkSelector)) {
|
||||||
|
// Prevent text selection
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
this.lastUrl = e.target.href;
|
||||||
|
this.showMenu(e);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
setTimeout(() => {
|
||||||
|
this.removeOpenListeners();
|
||||||
|
}, 1000);
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
addOpenListeners() {
|
||||||
|
document.addEventListener("mousedown", this);
|
||||||
|
document.addEventListener("keyup", this);
|
||||||
|
},
|
||||||
|
|
||||||
|
removeOpenListeners() {
|
||||||
|
document.removeEventListener("mousedown", this);
|
||||||
|
document.removeEventListener("keyup", this);
|
||||||
|
},
|
||||||
|
|
||||||
|
isMenuOpen() {
|
||||||
|
return !this.menuElement.hidden;
|
||||||
|
},
|
||||||
|
|
||||||
|
menuOpen() {
|
||||||
|
this.menuElement.hidden = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
menuClose() {
|
||||||
|
this.menuElement.hidden = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
getContainers() {
|
||||||
|
return browser.runtime.sendMessage({
|
||||||
|
method: "getContainers"
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async createMenu() {
|
||||||
|
if (this.menuElement) {
|
||||||
|
return this.menuElement;
|
||||||
|
}
|
||||||
|
const menuElement = document.createElement("ul");
|
||||||
|
menuElement.id = "containers-menu";
|
||||||
|
menuElement.hidden = true;
|
||||||
|
const containers = await this.getContainers();
|
||||||
|
containers.forEach((container) => {
|
||||||
|
const containerElement = document.createElement("li");
|
||||||
|
const spanElement = document.createElement("span");
|
||||||
|
spanElement.innerText = container.name;
|
||||||
|
containerElement.appendChild(spanElement);
|
||||||
|
containerElement.setAttribute("tabindex", 0);
|
||||||
|
const iconElement = document.createElement("div");
|
||||||
|
iconElement.classList.add("usercontext-icon");
|
||||||
|
iconElement.setAttribute("data-identity-icon", container.icon);
|
||||||
|
iconElement.setAttribute("data-identity-color", container.color);
|
||||||
|
containerElement.prepend(iconElement);
|
||||||
|
menuElement.appendChild(containerElement);
|
||||||
|
containerElement.addEventListener("click", (e) => {
|
||||||
|
this.openContainer(container);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
document.body.appendChild(menuElement);
|
||||||
|
this.menuElement = menuElement;
|
||||||
|
return menuElement;
|
||||||
|
},
|
||||||
|
|
||||||
|
async showMenu(e) {
|
||||||
|
const menuElement = await this.createMenu();
|
||||||
|
this.menuOpen();
|
||||||
|
menuElement.style.top = `${e.clientY}px`;
|
||||||
|
menuElement.style.left = `${e.clientX}px`;
|
||||||
|
menuElement.querySelector("div").focus();
|
||||||
|
},
|
||||||
|
|
||||||
|
openContainer(container) {
|
||||||
|
return browser.runtime.sendMessage({
|
||||||
|
method: "openTab",
|
||||||
|
url: this.lastUrl,
|
||||||
|
cookieStoreId: container.cookieStoreId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
menuClickHandler.init();
|
||||||
|
|
|
@ -59,11 +59,13 @@
|
||||||
{
|
{
|
||||||
"matches": ["<all_urls>"],
|
"matches": ["<all_urls>"],
|
||||||
"js": ["js/content-script.js"],
|
"js": ["js/content-script.js"],
|
||||||
"css": ["css/content.css"]
|
"css": ["css/user-context.css", "css/content.css"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
"web_accessible_resources": [
|
"web_accessible_resources": [
|
||||||
"/img/container-site-d-24.png"
|
"/img/container-site-d-24.png",
|
||||||
|
"/img/usercontext.svg",
|
||||||
|
"/img/filters.svg"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||||
<title>Containers browserAction Popup</title>
|
<title>Containers browserAction Popup</title>
|
||||||
|
<link rel="stylesheet" href="/css/user-context.css">
|
||||||
<link rel="stylesheet" href="/css/popup.css">
|
<link rel="stylesheet" href="/css/popup.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
Loading…
Add table
Reference in a new issue