Change: detect all kinds of manager in openManage
This commit is contained in:
parent
c2ac963232
commit
b66b015252
|
@ -1,6 +1,8 @@
|
||||||
/* global download prefs openURL FIREFOX CHROME VIVALDI
|
/* global download prefs openURL FIREFOX CHROME VIVALDI
|
||||||
debounce URLS ignoreChromeError getTab
|
debounce URLS ignoreChromeError getTab
|
||||||
styleManager msg navigatorUtil iconUtil workerUtil contentScripts sync */
|
styleManager msg navigatorUtil iconUtil workerUtil contentScripts sync
|
||||||
|
findExistTab createTab activateTab isTabReplaceable getActiveTab */
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// eslint-disable-next-line no-var
|
// eslint-disable-next-line no-var
|
||||||
|
@ -412,12 +414,32 @@ function openEditor(params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function openManage({options = false, search} = {}) {
|
function openManage({options = false, search} = {}) {
|
||||||
let url = 'manage.html';
|
let url = chrome.runtime.getURL('manage.html');
|
||||||
if (search) {
|
if (search) {
|
||||||
url += `?search=${encodeURIComponent(search)}`;
|
url += `?search=${encodeURIComponent(search)}`;
|
||||||
}
|
}
|
||||||
if (options) {
|
if (options) {
|
||||||
url += '#stylus-options';
|
url += '#stylus-options';
|
||||||
}
|
}
|
||||||
return openURL({url, currentWindow: null});
|
return findExistTab({
|
||||||
|
url,
|
||||||
|
currentWindow: null,
|
||||||
|
ignoreHash: true,
|
||||||
|
ignoreSearch: true
|
||||||
|
})
|
||||||
|
.then(tab => {
|
||||||
|
if (tab) {
|
||||||
|
return Promise.all([
|
||||||
|
activateTab(tab),
|
||||||
|
tab.url !== url && msg.sendTab(tab.id, {method: 'pushState', url})
|
||||||
|
.catch(console.warn)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
return getActiveTab().then(tab => {
|
||||||
|
if (isTabReplaceable(tab, url)) {
|
||||||
|
return activateTab(tab, {url});
|
||||||
|
}
|
||||||
|
return createTab({url});
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,18 +260,6 @@ const APPLY = (() => {
|
||||||
case 'updateCount':
|
case 'updateCount':
|
||||||
updateCount();
|
updateCount();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'trimHash':
|
|
||||||
if (IS_OWN_PAGE) {
|
|
||||||
// FIXME: currently we only do this in our own page. Is it safe to do
|
|
||||||
// it on all pages?
|
|
||||||
try {
|
|
||||||
// history.replaceState(null, null, ' ');
|
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
router.updateHash('');
|
|
||||||
} catch (err) {}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* exported getActiveTab onTabReady stringAsRegExp getTabRealURL openURL
|
/* exported getActiveTab onTabReady stringAsRegExp getTabRealURL openURL
|
||||||
getStyleWithNoCode tryRegExp sessionStorageHash download deepEqual
|
getStyleWithNoCode tryRegExp sessionStorageHash download deepEqual
|
||||||
closeCurrentTab capitalize CHROME_HAS_BORDER_BUG */
|
closeCurrentTab capitalize CHROME_HAS_BORDER_BUG */
|
||||||
/* global promisify msg */
|
/* global promisify */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const CHROME = Boolean(chrome.app) && parseInt(navigator.userAgent.match(/Chrom\w+\/(?:\d+\.){2}(\d+)|$/)[1]);
|
const CHROME = Boolean(chrome.app) && parseInt(navigator.userAgent.match(/Chrom\w+\/(?:\d+\.){2}(\d+)|$/)[1]);
|
||||||
|
@ -195,21 +195,38 @@ function onTabReady(tabOrId) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function urlToMatchPattern(url) {
|
function urlToMatchPattern(url, ignoreSearch) {
|
||||||
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns
|
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns
|
||||||
if (!/^(http|https|ws|wss|ftp|data|file)$/.test(url.protocol)) {
|
if (!/^(http|https|ws|wss|ftp|data|file)$/.test(url.protocol)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
if (ignoreSearch) {
|
||||||
|
return [
|
||||||
|
`${url.protocol}//${url.hostname}/${url.pathname}`,
|
||||||
|
`${url.protocol}//${url.hostname}/${url.pathname}?*`
|
||||||
|
];
|
||||||
|
}
|
||||||
// FIXME: is %2f allowed in pathname and search?
|
// FIXME: is %2f allowed in pathname and search?
|
||||||
return `${url.protocol}//${url.hostname}/${url.pathname}${url.search}`;
|
return `${url.protocol}//${url.hostname}/${url.pathname}${url.search}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function findExistTab(url, currentWindow) {
|
function findExistTab({url, currentWindow, ignoreHash = true, ignoreSearch = false}) {
|
||||||
url = new URL(url);
|
url = new URL(url);
|
||||||
const normalizedUrl = url.href.split('#')[0];
|
return queryTabs({url: urlToMatchPattern(url, ignoreSearch), currentWindow})
|
||||||
return queryTabs({url: urlToMatchPattern(url), currentWindow})
|
|
||||||
// FIXME: is tab.url always normalized?
|
// FIXME: is tab.url always normalized?
|
||||||
.then(tabs => tabs.find(tab => tab.url.split('#')[0] === normalizedUrl));
|
.then(tabs => tabs.find(matchTab));
|
||||||
|
|
||||||
|
function matchTab(tab) {
|
||||||
|
const tabUrl = new URL(tab.url);
|
||||||
|
return tabUrl.protocol === url.protocol &&
|
||||||
|
tabUrl.username === url.username &&
|
||||||
|
tabUrl.password === url.password &&
|
||||||
|
tabUrl.hostname === url.hostname &&
|
||||||
|
tabUrl.port === url.port &&
|
||||||
|
tabUrl.pathname === url.pathname &&
|
||||||
|
(ignoreSearch || tabUrl.search === url.search) &&
|
||||||
|
(ignoreHash || tabUrl.hash === url.hash);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -246,49 +263,49 @@ function openURL(options) {
|
||||||
if (!url.includes('://')) {
|
if (!url.includes('://')) {
|
||||||
url = chrome.runtime.getURL(url);
|
url = chrome.runtime.getURL(url);
|
||||||
}
|
}
|
||||||
return findExistTab(url, currentWindow)
|
return findExistTab({url, currentWindow}).then(tab => {
|
||||||
.then(tab => {
|
if (tab) {
|
||||||
if (!tab) {
|
|
||||||
return getActiveTab().then(maybeReplace);
|
|
||||||
}
|
|
||||||
// update url if only hash is different?
|
// update url if only hash is different?
|
||||||
if (tab.url !== url && tab.url.split('#')[0] === url.split('#')[0]) {
|
// we can't update URL if !url.includes('#') since it refreshes the page
|
||||||
if (url.includes('#')) {
|
if (tab.url !== url && tab.url.split('#')[0] === url.split('#')[0] &&
|
||||||
return activateTab(tab, {url, index});
|
url.includes('#')) {
|
||||||
} else {
|
return activateTab(tab, {url, index});
|
||||||
// we can't update URL directly since it refresh the page
|
|
||||||
return Promise.all([
|
|
||||||
activateTab(tab, {index}),
|
|
||||||
msg.sendTab(tab.id, {method: 'trimHash'}).catch(console.warn)
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return activateTab(tab, {index});
|
return activateTab(tab, {index});
|
||||||
});
|
|
||||||
|
|
||||||
// update current NTP or about:blank
|
|
||||||
// except when 'url' is chrome:// or chrome-extension:// in incognito
|
|
||||||
function maybeReplace(tab) {
|
|
||||||
const chromeInIncognito = tab && tab.incognito && url.startsWith('chrome');
|
|
||||||
const emptyTab = tab && URLS.emptyTab.includes(tab.url);
|
|
||||||
if (emptyTab && !chromeInIncognito) {
|
|
||||||
return activateTab(tab, {url, index}); // FIXME: should we move current empty tab?
|
|
||||||
}
|
}
|
||||||
if (newWindow) {
|
if (newWindow) {
|
||||||
return createWindow(Object.assign({url}, windowPosition));
|
return createWindow(Object.assign({url}, windowPosition));
|
||||||
}
|
}
|
||||||
const options = {url, index, active};
|
return getActiveTab().then(tab => {
|
||||||
// FF57+ supports openerTabId, but not in Android (indicated by the absence of chrome.windows)
|
if (isTabReplaceable(tab, url)) {
|
||||||
// FIXME: is it safe to assume that the current tab is the opener?
|
return activateTab(tab, {url, index});
|
||||||
if (tab && (!FIREFOX || FIREFOX >= 57 && chrome.windows) && !chromeInIncognito) {
|
}
|
||||||
options.openerTabId = tab.id;
|
const options = {url, index, active};
|
||||||
}
|
// FF57+ supports openerTabId, but not in Android (indicated by the absence of chrome.windows)
|
||||||
return createTab(options);
|
// FIXME: is it safe to assume that the current tab is the opener?
|
||||||
}
|
if (tab && !tab.incognito && (!FIREFOX || FIREFOX >= 57 && chrome.windows)) {
|
||||||
|
options.openerTabId = tab.id;
|
||||||
|
}
|
||||||
|
return createTab(options);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// replace empty tab (NTP or about:blank)
|
||||||
|
// except when new URL is chrome:// or chrome-extension:// and the empty tab is
|
||||||
|
// in incognito
|
||||||
|
function isTabReplaceable(tab, newUrl) {
|
||||||
|
if (!tab || !URLS.emptyTab.includes(tab.url)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// FIXME: why?
|
||||||
|
if (tab.incognito && newUrl.startsWith('chrome')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
function activateTab(tab, {url, index}) {
|
function activateTab(tab, {url, index} = {}) {
|
||||||
const options = {active: true};
|
const options = {active: true};
|
||||||
if (url) {
|
if (url) {
|
||||||
options.url = url;
|
options.url = url;
|
||||||
|
@ -297,7 +314,8 @@ function activateTab(tab, {url, index}) {
|
||||||
updateTab(tab.id, options),
|
updateTab(tab.id, options),
|
||||||
updateWindow(tab.windowId, {focused: true}),
|
updateWindow(tab.windowId, {focused: true}),
|
||||||
index != null && moveTabs(tab.id, {index})
|
index != null && moveTabs(tab.id, {index})
|
||||||
]);
|
])
|
||||||
|
.then(() => tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* global deepEqual */
|
/* global deepEqual msg */
|
||||||
/* exported router */
|
/* exported router */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
@ -8,6 +8,12 @@ const router = (() => {
|
||||||
document.addEventListener('DOMContentLoaded', () => update());
|
document.addEventListener('DOMContentLoaded', () => update());
|
||||||
window.addEventListener('popstate', () => update());
|
window.addEventListener('popstate', () => update());
|
||||||
window.addEventListener('hashchange', () => update());
|
window.addEventListener('hashchange', () => update());
|
||||||
|
msg.on(e => {
|
||||||
|
if (e.method === 'pushState' && e.url !== location.href) {
|
||||||
|
history.pushState(history.state, null, e.url);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
});
|
||||||
return {watch, updateSearch, getSearch, updateHash};
|
return {watch, updateSearch, getSearch, updateHash};
|
||||||
|
|
||||||
function watch(options, callback) {
|
function watch(options, callback) {
|
||||||
|
|
|
@ -150,9 +150,9 @@
|
||||||
<script src="js/promisify.js"></script>
|
<script src="js/promisify.js"></script>
|
||||||
<script src="js/dom.js"></script>
|
<script src="js/dom.js"></script>
|
||||||
<script src="js/messaging.js"></script>
|
<script src="js/messaging.js"></script>
|
||||||
<script src="js/router.js"></script>
|
|
||||||
<script src="js/prefs.js"></script>
|
<script src="js/prefs.js"></script>
|
||||||
<script src="js/msg.js"></script>
|
<script src="js/msg.js"></script>
|
||||||
|
<script src="js/router.js"></script>
|
||||||
<script src="content/style-injector.js"></script>
|
<script src="content/style-injector.js"></script>
|
||||||
<script src="content/apply.js"></script>
|
<script src="content/apply.js"></script>
|
||||||
<script src="js/localization.js"></script>
|
<script src="js/localization.js"></script>
|
||||||
|
|
|
@ -12,9 +12,7 @@ const filtersSelector = {
|
||||||
let initialized = false;
|
let initialized = false;
|
||||||
|
|
||||||
router.watch({search: ['search']}, ([search]) => {
|
router.watch({search: ['search']}, ([search]) => {
|
||||||
if (search != null) {
|
$('#search').value = search || '';
|
||||||
$('#search').value = search;
|
|
||||||
}
|
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
init();
|
init();
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user