Merge pull request #439 from siikamiika/popup-live-toggle
Popup live toggle
This commit is contained in:
commit
e6053eefa5
@ -19,18 +19,7 @@
|
|||||||
* apiOptionsGet
|
* apiOptionsGet
|
||||||
*/
|
*/
|
||||||
|
|
||||||
async function searchFrontendSetup() {
|
function injectSearchFrontend() {
|
||||||
await yomichan.prepare();
|
|
||||||
|
|
||||||
const optionsContext = {
|
|
||||||
depth: 0,
|
|
||||||
url: window.location.href
|
|
||||||
};
|
|
||||||
const options = await apiOptionsGet(optionsContext);
|
|
||||||
if (!options.scanning.enableOnSearchPage) { return; }
|
|
||||||
|
|
||||||
window.frontendInitializationData = {depth: 1, proxy: false};
|
|
||||||
|
|
||||||
const scriptSrcs = [
|
const scriptSrcs = [
|
||||||
'/mixed/js/text-scanner.js',
|
'/mixed/js/text-scanner.js',
|
||||||
'/fg/js/frontend-api-receiver.js',
|
'/fg/js/frontend-api-receiver.js',
|
||||||
@ -62,4 +51,29 @@ async function searchFrontendSetup() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
searchFrontendSetup();
|
async function main() {
|
||||||
|
await yomichan.prepare();
|
||||||
|
|
||||||
|
let optionsApplied = false;
|
||||||
|
|
||||||
|
const applyOptions = async () => {
|
||||||
|
const optionsContext = {
|
||||||
|
depth: 0,
|
||||||
|
url: window.location.href
|
||||||
|
};
|
||||||
|
const options = await apiOptionsGet(optionsContext);
|
||||||
|
if (!options.scanning.enableOnSearchPage || optionsApplied) { return; }
|
||||||
|
optionsApplied = true;
|
||||||
|
|
||||||
|
window.frontendInitializationData = {depth: 1, proxy: false, isSearchPage: true};
|
||||||
|
injectSearchFrontend();
|
||||||
|
|
||||||
|
yomichan.off('optionsUpdated', applyOptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
yomichan.on('optionsUpdated', applyOptions);
|
||||||
|
|
||||||
|
await applyOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
class QueryParser extends TextScanner {
|
class QueryParser extends TextScanner {
|
||||||
constructor({getOptionsContext, setContent, setSpinnerVisible}) {
|
constructor({getOptionsContext, setContent, setSpinnerVisible}) {
|
||||||
super(document.querySelector('#query-parser-content'), [], []);
|
super(document.querySelector('#query-parser-content'), () => [], []);
|
||||||
|
|
||||||
this.getOptionsContext = getOptionsContext;
|
this.getOptionsContext = getOptionsContext;
|
||||||
this.setContent = setContent;
|
this.setContent = setContent;
|
||||||
|
@ -24,49 +24,101 @@
|
|||||||
* apiOptionsGet
|
* apiOptionsGet
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
async function createIframePopupProxy(url, frameOffsetForwarder) {
|
||||||
|
const rootPopupInformationPromise = yomichan.getTemporaryListenerResult(
|
||||||
|
chrome.runtime.onMessage,
|
||||||
|
({action, params}, {resolve}) => {
|
||||||
|
if (action === 'rootPopupInformation') {
|
||||||
|
resolve(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
apiBroadcastTab('rootPopupRequestInformationBroadcast');
|
||||||
|
const {popupId, frameId} = await rootPopupInformationPromise;
|
||||||
|
|
||||||
|
const getFrameOffset = frameOffsetForwarder.getOffset.bind(frameOffsetForwarder);
|
||||||
|
|
||||||
|
const popup = new PopupProxy(popupId, 0, null, frameId, url, getFrameOffset);
|
||||||
|
await popup.prepare();
|
||||||
|
|
||||||
|
return popup;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getOrCreatePopup(depth) {
|
||||||
|
const popupHost = new PopupProxyHost();
|
||||||
|
await popupHost.prepare();
|
||||||
|
|
||||||
|
const popup = popupHost.getOrCreatePopup(null, null, depth);
|
||||||
|
|
||||||
|
return popup;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createPopupProxy(depth, id, parentFrameId, url) {
|
||||||
|
const popup = new PopupProxy(null, depth + 1, id, parentFrameId, url);
|
||||||
|
await popup.prepare();
|
||||||
|
|
||||||
|
return popup;
|
||||||
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
await yomichan.prepare();
|
await yomichan.prepare();
|
||||||
|
|
||||||
const data = window.frontendInitializationData || {};
|
const data = window.frontendInitializationData || {};
|
||||||
const {id, depth=0, parentFrameId, url, proxy=false} = data;
|
const {id, depth=0, parentFrameId, url=window.location.href, proxy=false, isSearchPage=false} = data;
|
||||||
|
|
||||||
const optionsContext = {depth, url};
|
const isIframe = !proxy && (window !== window.parent);
|
||||||
const options = await apiOptionsGet(optionsContext);
|
|
||||||
|
|
||||||
let popup;
|
const popups = {
|
||||||
if (!proxy && (window !== window.parent) && options.general.showIframePopupsInRootFrame) {
|
iframe: null,
|
||||||
const rootPopupInformationPromise = yomichan.getTemporaryListenerResult(
|
proxy: null,
|
||||||
chrome.runtime.onMessage,
|
normal: null
|
||||||
({action, params}, {resolve}) => {
|
};
|
||||||
if (action === 'rootPopupInformation') {
|
|
||||||
resolve(params);
|
let frontend = null;
|
||||||
}
|
let frontendPreparePromise = null;
|
||||||
|
let frameOffsetForwarder = null;
|
||||||
|
|
||||||
|
const applyOptions = async () => {
|
||||||
|
const optionsContext = {depth: isSearchPage ? 0 : depth, url};
|
||||||
|
const options = await apiOptionsGet(optionsContext);
|
||||||
|
|
||||||
|
if (!proxy && frameOffsetForwarder === null) {
|
||||||
|
frameOffsetForwarder = new FrameOffsetForwarder();
|
||||||
|
frameOffsetForwarder.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
let popup;
|
||||||
|
if (isIframe && options.general.showIframePopupsInRootFrame) {
|
||||||
|
popup = popups.iframe || await createIframePopupProxy(url, frameOffsetForwarder);
|
||||||
|
popups.iframe = popup;
|
||||||
|
} else if (proxy) {
|
||||||
|
popup = popups.proxy || await createPopupProxy(depth, id, parentFrameId, url);
|
||||||
|
popups.proxy = popup;
|
||||||
|
} else {
|
||||||
|
popup = popups.normal || await getOrCreatePopup(depth);
|
||||||
|
popups.normal = popup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frontend === null) {
|
||||||
|
frontend = new Frontend(popup);
|
||||||
|
frontendPreparePromise = frontend.prepare();
|
||||||
|
await frontendPreparePromise;
|
||||||
|
} else {
|
||||||
|
await frontendPreparePromise;
|
||||||
|
if (isSearchPage) {
|
||||||
|
const disabled = !options.scanning.enableOnSearchPage;
|
||||||
|
frontend.setDisabledOverride(disabled);
|
||||||
}
|
}
|
||||||
);
|
|
||||||
apiBroadcastTab('rootPopupRequestInformationBroadcast');
|
|
||||||
const {popupId, frameId} = await rootPopupInformationPromise;
|
|
||||||
|
|
||||||
const frameOffsetForwarder = new FrameOffsetForwarder();
|
if (isIframe) {
|
||||||
frameOffsetForwarder.start();
|
await frontend.setPopup(popup);
|
||||||
const getFrameOffset = frameOffsetForwarder.getOffset.bind(frameOffsetForwarder);
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
popup = new PopupProxy(popupId, 0, null, frameId, url, getFrameOffset);
|
yomichan.on('optionsUpdated', applyOptions);
|
||||||
await popup.prepare();
|
|
||||||
} else if (proxy) {
|
|
||||||
popup = new PopupProxy(null, depth + 1, id, parentFrameId, url);
|
|
||||||
await popup.prepare();
|
|
||||||
} else {
|
|
||||||
const frameOffsetForwarder = new FrameOffsetForwarder();
|
|
||||||
frameOffsetForwarder.start();
|
|
||||||
|
|
||||||
const popupHost = new PopupProxyHost();
|
await applyOptions();
|
||||||
await popupHost.prepare();
|
|
||||||
|
|
||||||
popup = popupHost.getOrCreatePopup(null, null, depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
const frontend = new Frontend(popup);
|
|
||||||
await frontend.prepare();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main();
|
main();
|
||||||
|
@ -29,11 +29,14 @@ class Frontend extends TextScanner {
|
|||||||
constructor(popup) {
|
constructor(popup) {
|
||||||
super(
|
super(
|
||||||
window,
|
window,
|
||||||
popup.isProxy() ? [] : [popup.getContainer()],
|
() => this.popup.isProxy() ? [] : [this.popup.getContainer()],
|
||||||
[(x, y) => this.popup.containsPoint(x, y)]
|
[(x, y) => this.popup.containsPoint(x, y)]
|
||||||
);
|
);
|
||||||
|
|
||||||
this.popup = popup;
|
this.popup = popup;
|
||||||
|
|
||||||
|
this._disabledOverride = false;
|
||||||
|
|
||||||
this.options = null;
|
this.options = null;
|
||||||
|
|
||||||
this.optionsContext = {
|
this.optionsContext = {
|
||||||
@ -132,8 +135,20 @@ class Frontend extends TextScanner {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setDisabledOverride(disabled) {
|
||||||
|
this._disabledOverride = disabled;
|
||||||
|
this.setEnabled(this.options.general.enable, this._canEnable());
|
||||||
|
}
|
||||||
|
|
||||||
|
async setPopup(popup) {
|
||||||
|
this.onSearchClear(false);
|
||||||
|
this.popup = popup;
|
||||||
|
await popup.setOptions(this.options);
|
||||||
|
}
|
||||||
|
|
||||||
async updateOptions() {
|
async updateOptions() {
|
||||||
this.setOptions(await apiOptionsGet(this.getOptionsContext()));
|
this.options = await apiOptionsGet(this.getOptionsContext());
|
||||||
|
this.setOptions(this.options, this._canEnable());
|
||||||
|
|
||||||
const ignoreNodes = ['.scan-disable', '.scan-disable *'];
|
const ignoreNodes = ['.scan-disable', '.scan-disable *'];
|
||||||
if (!this.options.scanning.enableOnPopupExpressions) {
|
if (!this.options.scanning.enableOnPopupExpressions) {
|
||||||
@ -259,7 +274,7 @@ class Frontend extends TextScanner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_broadcastRootPopupInformation() {
|
_broadcastRootPopupInformation() {
|
||||||
if (!this.popup.isProxy() && this.popup.depth === 0) {
|
if (!this.popup.isProxy() && this.popup.depth === 0 && this.popup.frameId === 0) {
|
||||||
apiBroadcastTab('rootPopupInformation', {popupId: this.popup.id, frameId: this.popup.frameId});
|
apiBroadcastTab('rootPopupInformation', {popupId: this.popup.id, frameId: this.popup.frameId});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -272,6 +287,10 @@ class Frontend extends TextScanner {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_canEnable() {
|
||||||
|
return this.popup.depth <= this.options.scanning.popupNestingMaxDepth && !this._disabledOverride;
|
||||||
|
}
|
||||||
|
|
||||||
async _updatePopupPosition() {
|
async _updatePopupPosition() {
|
||||||
const textSource = this.getCurrentTextSource();
|
const textSource = this.getCurrentTextSource();
|
||||||
if (textSource !== null && await this.popup.isVisible()) {
|
if (textSource !== null && await this.popup.isVisible()) {
|
||||||
|
@ -19,24 +19,7 @@
|
|||||||
* apiOptionsGet
|
* apiOptionsGet
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let popupNestedInitialized = false;
|
function injectPopupNested() {
|
||||||
|
|
||||||
async function popupNestedInitialize(id, depth, parentFrameId, url) {
|
|
||||||
if (popupNestedInitialized) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
popupNestedInitialized = true;
|
|
||||||
|
|
||||||
const optionsContext = {depth, url};
|
|
||||||
const options = await apiOptionsGet(optionsContext);
|
|
||||||
const popupNestingMaxDepth = options.scanning.popupNestingMaxDepth;
|
|
||||||
|
|
||||||
if (!(typeof popupNestingMaxDepth === 'number' && typeof depth === 'number' && depth < popupNestingMaxDepth)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.frontendInitializationData = {id, depth, parentFrameId, url, proxy: true};
|
|
||||||
|
|
||||||
const scriptSrcs = [
|
const scriptSrcs = [
|
||||||
'/mixed/js/text-scanner.js',
|
'/mixed/js/text-scanner.js',
|
||||||
'/fg/js/frontend-api-sender.js',
|
'/fg/js/frontend-api-sender.js',
|
||||||
@ -52,3 +35,33 @@ async function popupNestedInitialize(id, depth, parentFrameId, url) {
|
|||||||
document.body.appendChild(script);
|
document.body.appendChild(script);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function popupNestedInitialize(id, depth, parentFrameId, url) {
|
||||||
|
let optionsApplied = false;
|
||||||
|
|
||||||
|
const applyOptions = async () => {
|
||||||
|
const optionsContext = {depth, url};
|
||||||
|
const options = await apiOptionsGet(optionsContext);
|
||||||
|
const popupNestingMaxDepth = options.scanning.popupNestingMaxDepth;
|
||||||
|
|
||||||
|
const maxPopupDepthExceeded = !(
|
||||||
|
typeof popupNestingMaxDepth === 'number' &&
|
||||||
|
typeof depth === 'number' &&
|
||||||
|
depth < popupNestingMaxDepth
|
||||||
|
);
|
||||||
|
if (maxPopupDepthExceeded || optionsApplied) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
optionsApplied = true;
|
||||||
|
|
||||||
|
window.frontendInitializationData = {id, depth, parentFrameId, url, proxy: true};
|
||||||
|
injectPopupNested();
|
||||||
|
|
||||||
|
yomichan.off('optionsUpdated', applyOptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
yomichan.on('optionsUpdated', applyOptions);
|
||||||
|
|
||||||
|
await applyOptions();
|
||||||
|
}
|
||||||
|
@ -46,7 +46,7 @@ class TextScanner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMouseOver(e) {
|
onMouseOver(e) {
|
||||||
if (this.ignoreElements.includes(e.target)) {
|
if (this.ignoreElements().includes(e.target)) {
|
||||||
this.scanTimerClear();
|
this.scanTimerClear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -224,8 +224,8 @@ class TextScanner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setEnabled(enabled) {
|
setEnabled(enabled, canEnable) {
|
||||||
if (enabled) {
|
if (enabled && canEnable) {
|
||||||
if (!this.enabled) {
|
if (!this.enabled) {
|
||||||
this.hookEvents();
|
this.hookEvents();
|
||||||
this.enabled = true;
|
this.enabled = true;
|
||||||
@ -271,9 +271,9 @@ class TextScanner {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
setOptions(options) {
|
setOptions(options, canEnable=true) {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.setEnabled(this.options.general.enable);
|
this.setEnabled(this.options.general.enable, canEnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
async searchAt(x, y, cause) {
|
async searchAt(x, y, cause) {
|
||||||
|
Loading…
Reference in New Issue
Block a user