Context popup improvements (#1039)
* Refactor context-main.js * Simplify tags * Use flex layout * Use image masks for icons, update styles * Remove old classes * Add profile button * Add support for profile selection * Add title * Swap the options and search link order * Fix title
This commit is contained in:
parent
b0a5650625
commit
e5255a03e6
@ -2,7 +2,8 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
|
<title>Yomichan Action Popup</title>
|
||||||
<link rel="icon" type="image/png" href="/mixed/img/icon16.png" sizes="16x16">
|
<link rel="icon" type="image/png" href="/mixed/img/icon16.png" sizes="16x16">
|
||||||
<link rel="icon" type="image/png" href="/mixed/img/icon19.png" sizes="19x19">
|
<link rel="icon" type="image/png" href="/mixed/img/icon19.png" sizes="19x19">
|
||||||
<link rel="icon" type="image/png" href="/mixed/img/icon32.png" sizes="32x32">
|
<link rel="icon" type="image/png" href="/mixed/img/icon32.png" sizes="32x32">
|
||||||
@ -19,13 +20,18 @@
|
|||||||
<input type="checkbox" id="enable-search">
|
<input type="checkbox" id="enable-search">
|
||||||
<div class="toggle-group">
|
<div class="toggle-group">
|
||||||
<span class="toggle-on">On</span>
|
<span class="toggle-on">On</span>
|
||||||
<span class="btnx btn-defaulxt toggle-off">Off</span>
|
<span class="toggle-off">Off</span>
|
||||||
<span class="btnx xbtn-default toggle-handle"></span>
|
<span class="toggle-handle"></span>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
<div class="nav-button-container">
|
<div class="nav-button-container">
|
||||||
<a class="nav-button action-open-search" data-icon="magnifying-glass" title="Search (Alt + Insert) (Middle click to open in new tab)"></a>
|
<button class="nav-button action-select-profile" data-icon="profile" title="Change primary profile">
|
||||||
|
<span class="profile-select-container"><select class="profile-select" id="profile-select">
|
||||||
|
<optgroup label="Primary Profile" id="profile-select-option-group"></optgroup>
|
||||||
|
</select></span>
|
||||||
|
</button>
|
||||||
<a class="nav-button action-open-options" data-icon="cog" title="Options (Middle click to open in new tab)"></a>
|
<a class="nav-button action-open-options" data-icon="cog" title="Options (Middle click to open in new tab)"></a>
|
||||||
|
<a class="nav-button action-open-search" data-icon="magnifying-glass" title="Search (Alt + Insert) (Middle click to open in new tab)"></a>
|
||||||
<a class="nav-button action-open-help" data-icon="question-mark" title="Help"></a>
|
<a class="nav-button action-open-help" data-icon="question-mark" title="Help"></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -33,7 +39,7 @@
|
|||||||
<div id="full">
|
<div id="full">
|
||||||
<h3 id="extension-info">Yomichan</h3>
|
<h3 id="extension-info">Yomichan</h3>
|
||||||
<label class="link-group">
|
<label class="link-group">
|
||||||
<span class="link-group-icon"><input type="checkbox" id="enable-search2" /></span><span class="link-group-label">Enable content scanning</span>
|
<span class="link-group-icon"><input type="checkbox" id="enable-search2"></span><span class="link-group-label">Enable content scanning</span>
|
||||||
</label>
|
</label>
|
||||||
<a class="link-group action-open-options">
|
<a class="link-group action-open-options">
|
||||||
<span class="link-group-icon" data-icon="chevron"></span><span class="link-group-label">Options</span>
|
<span class="link-group-icon" data-icon="chevron"></span><span class="link-group-label">Options</span>
|
||||||
|
@ -35,7 +35,9 @@ label {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#mini {
|
#mini {
|
||||||
text-align: center;
|
display: flex;
|
||||||
|
flex-flow: column nowrap;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
#full {
|
#full {
|
||||||
display: none;
|
display: none;
|
||||||
@ -243,10 +245,17 @@ body[data-loaded=true] .toggle-group {
|
|||||||
display: block;
|
display: block;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
background-position: center center;
|
|
||||||
background-size: 16px 16px;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
|
background-color: #333333;
|
||||||
|
mask-repeat: no-repeat;
|
||||||
|
mask-position: center center;
|
||||||
|
mask-mode: alpha;
|
||||||
|
mask-size: 16px 16px;
|
||||||
|
-webkit-mask-repeat: no-repeat;
|
||||||
|
-webkit-mask-position: center center;
|
||||||
|
-webkit-mask-mode: alpha;
|
||||||
|
-webkit-mask-size: 16px 16px;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
.nav-button:hover {
|
.nav-button:hover {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
@ -264,19 +273,67 @@ body[data-loaded=true] .toggle-group {
|
|||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
.nav-button[data-icon=magnifying-glass]::after {
|
.nav-button[data-icon=magnifying-glass]::after {
|
||||||
background-image: url(/mixed/img/magnifying-glass.svg);
|
mask-image: url(/mixed/img/magnifying-glass.svg);
|
||||||
|
-webkit-mask-image: url(/mixed/img/magnifying-glass.svg);
|
||||||
}
|
}
|
||||||
.nav-button[data-icon=cog]::after {
|
.nav-button[data-icon=cog]::after {
|
||||||
background-image: url(/mixed/img/cog.svg);
|
mask-image: url(/mixed/img/cog.svg);
|
||||||
|
-webkit-mask-image: url(/mixed/img/cog.svg);
|
||||||
}
|
}
|
||||||
.nav-button[data-icon=question-mark]::after {
|
.nav-button[data-icon=question-mark]::after {
|
||||||
background-image: url(/mixed/img/question-mark-circle.svg);
|
mask-image: url(/mixed/img/question-mark-circle.svg);
|
||||||
|
-webkit-mask-image: url(/mixed/img/question-mark-circle.svg);
|
||||||
}
|
}
|
||||||
.nav-button:first-of-type {
|
.nav-button[data-icon=profile]::after {
|
||||||
|
mask-image: url(/mixed/img/profile.svg);
|
||||||
|
-webkit-mask-image: url(/mixed/img/profile.svg);
|
||||||
|
}
|
||||||
|
.nav-button:first-child {
|
||||||
border-top-left-radius: 3px;
|
border-top-left-radius: 3px;
|
||||||
border-bottom-left-radius: 3px;
|
border-bottom-left-radius: 3px;
|
||||||
}
|
}
|
||||||
.nav-button:last-of-type {
|
.nav-button:last-child {
|
||||||
border-top-right-radius: 3px;
|
border-top-right-radius: 3px;
|
||||||
border-bottom-right-radius: 3px;
|
border-bottom-right-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.action-select-profile {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.profile-select-container {
|
||||||
|
position: absolute;
|
||||||
|
left: -1px;
|
||||||
|
top: -1px;
|
||||||
|
right: -1px;
|
||||||
|
bottom: -1px;
|
||||||
|
}
|
||||||
|
select.profile-select {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.375em;
|
||||||
|
appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
opacity: 0;
|
||||||
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.profile-select optgroup {
|
||||||
|
color: #666666;
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
.profile-select option {
|
||||||
|
color: #333333;
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
background-color: initial;
|
||||||
|
}
|
||||||
|
@ -19,73 +19,127 @@
|
|||||||
* api
|
* api
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function showExtensionInfo(manifest) {
|
class DisplayController {
|
||||||
const node = document.getElementById('extension-info');
|
constructor() {
|
||||||
if (node === null) { return; }
|
this._optionsFull = null;
|
||||||
|
}
|
||||||
|
|
||||||
node.textContent = `${manifest.name} v${manifest.version}`;
|
async prepare() {
|
||||||
}
|
const manifest = chrome.runtime.getManifest();
|
||||||
|
|
||||||
function setupButtonEvents(selector, command, url) {
|
this._showExtensionInfo(manifest);
|
||||||
const nodes = document.querySelectorAll(selector);
|
this._setupEnvironment();
|
||||||
for (const node of nodes) {
|
this._setupButtonEvents('.action-open-search', 'search', chrome.runtime.getURL('/bg/search.html'));
|
||||||
node.addEventListener('click', (e) => {
|
this._setupButtonEvents('.action-open-options', 'options', chrome.runtime.getURL(manifest.options_ui.page));
|
||||||
if (e.button !== 0) { return; }
|
this._setupButtonEvents('.action-open-help', 'help', 'https://foosoft.net/projects/yomichan/');
|
||||||
api.commandExec(command, {mode: e.ctrlKey ? 'newTab' : 'existingOrNewTab'});
|
|
||||||
e.preventDefault();
|
|
||||||
}, false);
|
|
||||||
node.addEventListener('auxclick', (e) => {
|
|
||||||
if (e.button !== 1) { return; }
|
|
||||||
api.commandExec(command, {mode: 'newTab'});
|
|
||||||
e.preventDefault();
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
if (typeof url === 'string') {
|
const optionsFull = await api.optionsGetFull();
|
||||||
node.href = url;
|
this._optionsFull = optionsFull;
|
||||||
node.target = '_blank';
|
|
||||||
node.rel = 'noopener';
|
const {profiles, profileCurrent} = optionsFull;
|
||||||
|
const primaryProfile = (profileCurrent >= 0 && profileCurrent < profiles.length) ? profiles[profileCurrent] : null;
|
||||||
|
if (primaryProfile !== null) {
|
||||||
|
this._setupOptions(primaryProfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._updateProfileSelect(profiles, profileCurrent);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
document.body.dataset.loaded = 'true';
|
||||||
|
}, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private
|
||||||
|
|
||||||
|
_showExtensionInfo(manifest) {
|
||||||
|
const node = document.getElementById('extension-info');
|
||||||
|
if (node === null) { return; }
|
||||||
|
|
||||||
|
node.textContent = `${manifest.name} v${manifest.version}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
_setupButtonEvents(selector, command, url) {
|
||||||
|
const nodes = document.querySelectorAll(selector);
|
||||||
|
for (const node of nodes) {
|
||||||
|
node.addEventListener('click', (e) => {
|
||||||
|
if (e.button !== 0) { return; }
|
||||||
|
api.commandExec(command, {mode: e.ctrlKey ? 'newTab' : 'existingOrNewTab'});
|
||||||
|
e.preventDefault();
|
||||||
|
}, false);
|
||||||
|
node.addEventListener('auxclick', (e) => {
|
||||||
|
if (e.button !== 1) { return; }
|
||||||
|
api.commandExec(command, {mode: 'newTab'});
|
||||||
|
e.preventDefault();
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
if (typeof url === 'string') {
|
||||||
|
node.href = url;
|
||||||
|
node.target = '_blank';
|
||||||
|
node.rel = 'noopener';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
async function setupEnvironment() {
|
async _setupEnvironment() {
|
||||||
// Firefox mobile opens this page as a full webpage.
|
// Firefox mobile opens this page as a full webpage.
|
||||||
const {browser} = await api.getEnvironmentInfo();
|
const {browser} = await api.getEnvironmentInfo();
|
||||||
document.documentElement.dataset.mode = (browser === 'firefox-mobile' ? 'full' : 'mini');
|
document.documentElement.dataset.mode = (browser === 'firefox-mobile' ? 'full' : 'mini');
|
||||||
}
|
|
||||||
|
|
||||||
async function setupOptions() {
|
|
||||||
const optionsContext = {
|
|
||||||
depth: 0,
|
|
||||||
url: window.location.href
|
|
||||||
};
|
|
||||||
const options = await api.optionsGet(optionsContext);
|
|
||||||
|
|
||||||
const extensionEnabled = options.general.enable;
|
|
||||||
const onToggleChanged = () => api.commandExec('toggle');
|
|
||||||
for (const toggle of document.querySelectorAll('#enable-search,#enable-search2')) {
|
|
||||||
toggle.checked = extensionEnabled;
|
|
||||||
toggle.addEventListener('change', onToggleChanged, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
_setupOptions({options}) {
|
||||||
document.body.dataset.loaded = 'true';
|
const extensionEnabled = options.general.enable;
|
||||||
}, 10);
|
const onToggleChanged = () => api.commandExec('toggle');
|
||||||
|
for (const toggle of document.querySelectorAll('#enable-search,#enable-search2')) {
|
||||||
|
toggle.checked = extensionEnabled;
|
||||||
|
toggle.addEventListener('change', onToggleChanged, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_updateProfileSelect(profiles, profileCurrent) {
|
||||||
|
const select = document.querySelector('#profile-select');
|
||||||
|
const optionGroup = document.querySelector('#profile-select-option-group');
|
||||||
|
const fragment = document.createDocumentFragment();
|
||||||
|
for (let i = 0, ii = profiles.length; i < ii; ++i) {
|
||||||
|
const {name} = profiles[i];
|
||||||
|
const option = document.createElement('option');
|
||||||
|
option.textContent = name;
|
||||||
|
option.value = `${i}`;
|
||||||
|
fragment.appendChild(option);
|
||||||
|
}
|
||||||
|
optionGroup.textContent = '';
|
||||||
|
optionGroup.appendChild(fragment);
|
||||||
|
select.value = `${profileCurrent}`;
|
||||||
|
|
||||||
|
select.addEventListener('change', this._onProfileSelectChange.bind(this), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
_onProfileSelectChange(e) {
|
||||||
|
const value = parseInt(e.currentTarget.value, 10);
|
||||||
|
if (typeof value === 'number' && Number.isFinite(value) && value >= 0 && value <= this._optionsFull.profiles.length) {
|
||||||
|
this._setPrimaryProfileIndex(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async _setPrimaryProfileIndex(value) {
|
||||||
|
return await api.modifySettings(
|
||||||
|
[{
|
||||||
|
action: 'set',
|
||||||
|
path: 'profileCurrent',
|
||||||
|
value,
|
||||||
|
scope: 'global'
|
||||||
|
}]
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
api.forwardLogsToBackend();
|
api.forwardLogsToBackend();
|
||||||
await yomichan.backendReady();
|
await yomichan.backendReady();
|
||||||
|
|
||||||
const manifest = chrome.runtime.getManifest();
|
|
||||||
|
|
||||||
api.logIndicatorClear();
|
api.logIndicatorClear();
|
||||||
showExtensionInfo(manifest);
|
|
||||||
setupEnvironment();
|
const displayController = new DisplayController();
|
||||||
setupOptions();
|
displayController.prepare();
|
||||||
setupButtonEvents('.action-open-search', 'search', chrome.runtime.getURL('/bg/search.html'));
|
|
||||||
setupButtonEvents('.action-open-options', 'options', chrome.runtime.getURL(manifest.options_ui.page));
|
|
||||||
setupButtonEvents('.action-open-help', 'help', 'https://foosoft.net/projects/yomichan/');
|
|
||||||
|
|
||||||
yomichan.ready();
|
yomichan.ready();
|
||||||
})();
|
})();
|
||||||
|
Loading…
Reference in New Issue
Block a user