Popup window options (#1245)
* Add popupWindow options * Add toBoolean converter * Add settings * Use new options * Add test link * Fix window state not working * Make the window section advanced only
This commit is contained in:
parent
dc4d659184
commit
8766744aa4
@ -230,7 +230,7 @@ h3 {
|
||||
font-size: calc(1em / 1.125);
|
||||
color: var(--text-color-light);
|
||||
}
|
||||
.heading-link-light {
|
||||
a.heading-link-light {
|
||||
color: var(--text-color-light);
|
||||
}
|
||||
.heading-description,
|
||||
|
@ -63,6 +63,7 @@
|
||||
"type": "object",
|
||||
"required": [
|
||||
"general",
|
||||
"popupWindow",
|
||||
"audio",
|
||||
"scanning",
|
||||
"translation",
|
||||
@ -288,6 +289,57 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"popupWindow": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"width",
|
||||
"height",
|
||||
"left",
|
||||
"top",
|
||||
"useLeft",
|
||||
"useTop",
|
||||
"windowType",
|
||||
"windowState"
|
||||
],
|
||||
"properties": {
|
||||
"width": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"default": 400
|
||||
},
|
||||
"height": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"default": 250
|
||||
},
|
||||
"left": {
|
||||
"type": "integer",
|
||||
"default": 0
|
||||
},
|
||||
"top": {
|
||||
"type": "integer",
|
||||
"default": 0
|
||||
},
|
||||
"useLeft": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"useTop": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"windowType": {
|
||||
"type": "string",
|
||||
"enum": ["normal", "popup"],
|
||||
"default": "popup"
|
||||
},
|
||||
"windowState": {
|
||||
"type": "string",
|
||||
"enum": ["normal", "maximized", "fullscreen"],
|
||||
"default": "normal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"audio": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
@ -818,25 +818,12 @@ class Backend {
|
||||
|
||||
// Create a new window
|
||||
const options = this.getOptions({current: true});
|
||||
const {popupWidth, popupHeight} = options.general;
|
||||
const popupWindow = await new Promise((resolve, reject) => {
|
||||
chrome.windows.create(
|
||||
{
|
||||
url: baseUrl,
|
||||
width: popupWidth,
|
||||
height: popupHeight,
|
||||
type: 'popup'
|
||||
},
|
||||
(result) => {
|
||||
const error = chrome.runtime.lastError;
|
||||
if (error) {
|
||||
reject(new Error(error.message));
|
||||
} else {
|
||||
resolve(result);
|
||||
const createData = this._getSearchPopupWindowCreateData(baseUrl, options);
|
||||
const {popupWindow: {windowState}} = options;
|
||||
const popupWindow = await this._createWindow(createData);
|
||||
if (windowState !== 'normal') {
|
||||
await this._updateWindow(popupWindow.id, {state: windowState});
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
const {tabs} = popupWindow;
|
||||
if (tabs.length === 0) {
|
||||
@ -856,6 +843,52 @@ class Backend {
|
||||
return {tab, created: true};
|
||||
}
|
||||
|
||||
_getSearchPopupWindowCreateData(url, options) {
|
||||
const {popupWindow: {width, height, left, top, useLeft, useTop, windowType}} = options;
|
||||
return {
|
||||
url,
|
||||
width,
|
||||
height,
|
||||
left: useLeft ? left : void 0,
|
||||
top: useTop ? top : void 0,
|
||||
type: windowType,
|
||||
state: 'normal'
|
||||
};
|
||||
}
|
||||
|
||||
_createWindow(createData) {
|
||||
return new Promise((resolve, reject) => {
|
||||
chrome.windows.create(
|
||||
createData,
|
||||
(result) => {
|
||||
const error = chrome.runtime.lastError;
|
||||
if (error) {
|
||||
reject(new Error(error.message));
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
_updateWindow(windowId, updateInfo) {
|
||||
return new Promise((resolve, reject) => {
|
||||
chrome.windows.update(
|
||||
windowId,
|
||||
updateInfo,
|
||||
(result) => {
|
||||
const error = chrome.runtime.lastError;
|
||||
if (error) {
|
||||
reject(new Error(error.message));
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
_updateSearchQuery(tabId, text, animate) {
|
||||
return this._sendMessageTabPromise(
|
||||
tabId,
|
||||
|
@ -689,6 +689,7 @@ class OptionsUtil {
|
||||
// Changed general.popupActionBarLocation.
|
||||
// Added inputs.hotkeys.
|
||||
// Added anki.suspendNewCards.
|
||||
// Added popupWindow.
|
||||
for (const profile of options.profiles) {
|
||||
profile.options.translation.textReplacements = {
|
||||
searchOriginal: true,
|
||||
@ -735,6 +736,16 @@ class OptionsUtil {
|
||||
]
|
||||
};
|
||||
profile.options.anki.suspendNewCards = false;
|
||||
profile.options.popupWindow = {
|
||||
width: profile.options.general.popupWidth,
|
||||
height: profile.options.general.popupHeight,
|
||||
left: 0,
|
||||
top: 0,
|
||||
useLeft: false,
|
||||
useTop: false,
|
||||
windowType: 'popup',
|
||||
windowState: 'normal'
|
||||
};
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ class GenericSettingController {
|
||||
['splitTags', this._splitTags.bind(this)],
|
||||
['joinTags', this._joinTags.bind(this)],
|
||||
['toNumber', this._toNumber.bind(this)],
|
||||
['toBoolean', this._toBoolean.bind(this)],
|
||||
['toString', this._toString.bind(this)],
|
||||
['conditionalConvert', this._conditionalConvert.bind(this)]
|
||||
]);
|
||||
@ -206,6 +207,10 @@ class GenericSettingController {
|
||||
return DOMDataBinder.convertToNumber(value, constraints);
|
||||
}
|
||||
|
||||
_toBoolean(value) {
|
||||
return (value === 'true');
|
||||
}
|
||||
|
||||
_toString(value) {
|
||||
return `${value}`;
|
||||
}
|
||||
|
38
ext/bg/js/settings2/popup-window-controller.js
Normal file
38
ext/bg/js/settings2/popup-window-controller.js
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Yomichan Authors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* global
|
||||
* api
|
||||
*/
|
||||
|
||||
class PopupWindowController {
|
||||
prepare() {
|
||||
const testLink = document.querySelector('#test-window-open-link');
|
||||
testLink.addEventListener('click', this._onTestWindowOpenLinkClick.bind(this), false);
|
||||
}
|
||||
|
||||
// Private
|
||||
|
||||
_onTestWindowOpenLinkClick(e) {
|
||||
e.preventDefault();
|
||||
this._testWindowOpen();
|
||||
}
|
||||
|
||||
async _testWindowOpen() {
|
||||
await api.getOrCreateSearchPopup({focus: true});
|
||||
}
|
||||
}
|
@ -29,6 +29,7 @@
|
||||
* ModalController
|
||||
* NestedPopupsController
|
||||
* PopupPreviewController
|
||||
* PopupWindowController
|
||||
* ProfileController
|
||||
* ScanInputsController
|
||||
* ScanInputsSimpleController
|
||||
@ -132,6 +133,9 @@ async function setupGenericSettingsController(genericSettingController) {
|
||||
const keyboardShortcutController = new KeyboardShortcutController(settingsController);
|
||||
keyboardShortcutController.prepare();
|
||||
|
||||
const popupWindowController = new PopupWindowController();
|
||||
popupWindowController.prepare();
|
||||
|
||||
await Promise.all(preparePromises);
|
||||
|
||||
document.documentElement.dataset.loaded = 'true';
|
||||
|
@ -28,7 +28,7 @@
|
||||
<a href="#!popup" class="outline-item"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="popup"></span></span><span class="outline-item-label">Popup</span></a>
|
||||
<a href="#!popup-appearance" class="outline-item"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="palette"></span></span><span class="outline-item-label">Appearance</span></a>
|
||||
<a href="#!popup-size" class="outline-item"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="popup-size"></span></span><span class="outline-item-label">Position & Size</span></a>
|
||||
<a href="#!window" class="outline-item"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="window"></span></span><span class="outline-item-label">Window</span></a>
|
||||
<a href="#!window" class="outline-item advanced-only"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="window"></span></span><span class="outline-item-label">Window</span></a>
|
||||
<a href="#!audio" class="outline-item"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="speaker"></span></span><span class="outline-item-label">Audio</span></a>
|
||||
<a href="#!text-parsing" class="outline-item"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="text-parsing"></span></span><span class="outline-item-label">Text Parsing</span></a>
|
||||
<a href="#!sentence-parsing" class="outline-item advanced-only"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="sentence-parsing"></span></span><span class="outline-item-label">Sentence Parsing</span></a>
|
||||
@ -921,11 +921,12 @@
|
||||
</div>
|
||||
|
||||
<!-- Window -->
|
||||
<div class="heading-container">
|
||||
<div class="heading-container advanced-only">
|
||||
<div class="heading-container-icon"><span class="icon" data-icon="window"></span></div>
|
||||
<div class="heading-container-left"><h2 id="window"><a href="#!window">Window</a></h2></div>
|
||||
<div class="heading-container-right"><a class="heading-link-light" id="test-window-open-link">Open…</a></div>
|
||||
</div>
|
||||
<div class="settings-group">
|
||||
<div class="settings-group advanced-only">
|
||||
<div class="settings-item">
|
||||
<div class="settings-item-inner">
|
||||
<div class="settings-item-left">
|
||||
@ -989,6 +990,123 @@
|
||||
<input type="number" min="0" step="1" data-setting="general.maximumClipboardSearchLength">
|
||||
</div>
|
||||
</div></div>
|
||||
<div class="settings-item"><div class="settings-item-inner settings-item-inner-wrappable">
|
||||
<div class="settings-item-left">
|
||||
<div class="settings-item-label">Size</div>
|
||||
<div class="settings-item-description">Control the size of the window, in pixels.</div>
|
||||
</div>
|
||||
<div class="settings-item-right">
|
||||
<div class="settings-item-group">
|
||||
<div class="settings-item-group-item">
|
||||
<div class="settings-item-group-item-label">Width</div>
|
||||
<input type="number" class="short-width short-height" min="0" step="1" data-setting="popupWindow.width">
|
||||
</div>
|
||||
<div class="settings-item-group-item">
|
||||
<div class="settings-item-group-item-label">Height</div>
|
||||
<input type="number" class="short-width short-height" min="0" step="1" data-setting="popupWindow.height">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div></div>
|
||||
<div class="settings-item"><div class="settings-item-inner settings-item-inner-wrappable">
|
||||
<div class="settings-item-left">
|
||||
<div class="settings-item-label">Left position</div>
|
||||
<div class="settings-item-description">Control the left position of the window, in pixels.</div>
|
||||
</div>
|
||||
<div class="settings-item-right">
|
||||
<div class="settings-item-group">
|
||||
<div class="settings-item-group-item" id="popup-window-left-container" hidden>
|
||||
<div class="settings-item-group-item-label">x</div>
|
||||
<input type="number" class="short-width short-height" step="1" data-setting="popupWindow.left">
|
||||
</div>
|
||||
<div class="settings-item-group-item">
|
||||
<div class="settings-item-group-item-label">Mode</div>
|
||||
<select class="short-width short-height" data-setting="popupWindow.useLeft"
|
||||
data-transform='[
|
||||
{
|
||||
"step": "pre",
|
||||
"type": "toBoolean"
|
||||
},
|
||||
{
|
||||
"type": "setVisibility",
|
||||
"selector": "#popup-window-left-container",
|
||||
"condition": {"op": "===", "value": true}
|
||||
},
|
||||
{
|
||||
"step": "post",
|
||||
"type": "toString"
|
||||
}
|
||||
]'
|
||||
>
|
||||
<option value="false">Auto</option>
|
||||
<option value="true">Manual</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div></div>
|
||||
<div class="settings-item"><div class="settings-item-inner settings-item-inner-wrappable">
|
||||
<div class="settings-item-left">
|
||||
<div class="settings-item-label">Top position</div>
|
||||
<div class="settings-item-description">Control the top position of the window, in pixels.</div>
|
||||
</div>
|
||||
<div class="settings-item-right">
|
||||
<div class="settings-item-group">
|
||||
<div class="settings-item-group-item" id="popup-window-top-container" hidden>
|
||||
<div class="settings-item-group-item-label">y</div>
|
||||
<input type="number" class="short-width short-height" step="1" data-setting="popupWindow.top">
|
||||
</div>
|
||||
<div class="settings-item-group-item">
|
||||
<div class="settings-item-group-item-label">Mode</div>
|
||||
<select class="short-width short-height" data-setting="popupWindow.useTop"
|
||||
data-transform='[
|
||||
{
|
||||
"step": "pre",
|
||||
"type": "toBoolean"
|
||||
},
|
||||
{
|
||||
"type": "setVisibility",
|
||||
"selector": "#popup-window-top-container",
|
||||
"condition": {"op": "===", "value": true}
|
||||
},
|
||||
{
|
||||
"step": "post",
|
||||
"type": "toString"
|
||||
}
|
||||
]'
|
||||
>
|
||||
<option value="false">Auto</option>
|
||||
<option value="true">Manual</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div></div>
|
||||
<div class="settings-item"><div class="settings-item-inner settings-item-inner-wrappable">
|
||||
<div class="settings-item-left">
|
||||
<div class="settings-item-label">Window style</div>
|
||||
<div class="settings-item-description">Change the appearance of the window.</div>
|
||||
</div>
|
||||
<div class="settings-item-right">
|
||||
<div class="settings-item-group">
|
||||
<div class="settings-item-group-item">
|
||||
<div class="settings-item-group-item-label">Type</div>
|
||||
<select class="short-width short-height" data-setting="popupWindow.windowType">
|
||||
<option value="normal">Normal</option>
|
||||
<option value="popup">Popup</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="settings-item-group-item">
|
||||
<div class="settings-item-group-item-label">State</div>
|
||||
<select class="short-width short-height" data-setting="popupWindow.windowState">
|
||||
<option value="normal">Normal</option>
|
||||
<option value="maximized">Maximized</option>
|
||||
<option value="fullscreen">Fullscreen</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
|
||||
<!-- Audio -->
|
||||
@ -2971,6 +3089,7 @@
|
||||
|
||||
<script src="/bg/js/settings2/keyboard-shortcuts-controller.js"></script>
|
||||
<script src="/bg/js/settings2/nested-popups-controller.js"></script>
|
||||
<script src="/bg/js/settings2/popup-window-controller.js"></script>
|
||||
<script src="/bg/js/settings2/secondary-search-dictionary-controller.js"></script>
|
||||
<script src="/bg/js/settings2/sentence-termination-characters-controller.js"></script>
|
||||
<script src="/bg/js/settings2/settings-display-controller.js"></script>
|
||||
|
@ -457,6 +457,16 @@ function createProfileOptionsUpdatedTestData1() {
|
||||
{action: 'viewNote', key: 'KeyV', modifiers: ['alt'], scopes: ['popup', 'search'], enabled: true},
|
||||
{action: 'copyHostSelection', key: 'KeyC', modifiers: ['ctrl'], scopes: ['popup', 'search'], enabled: true}
|
||||
]
|
||||
},
|
||||
popupWindow: {
|
||||
width: 400,
|
||||
height: 250,
|
||||
left: 0,
|
||||
top: 0,
|
||||
useLeft: false,
|
||||
useTop: false,
|
||||
windowType: 'popup',
|
||||
windowState: 'normal'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user