diff --git a/src/content_scripts/main.js b/src/content_scripts/main.js index 8f5ed5653d..750f137514 100644 --- a/src/content_scripts/main.js +++ b/src/content_scripts/main.js @@ -107,6 +107,26 @@ document.documentElement.append(script); }); + /** + * Shows an informative modal if the extension context is invalidated (e.g. after extension is autoupdated + * or manually disabled in Chromium). Should do nothing in Firefox, which stops running all extension + * context javascript immediately. + */ + const warnOnExtensionContextInvalidated = async () => { + const { showContextInvalidatedModal } = await import(browser.runtime.getURL('/utils/modals.js')); + + const isExtensionContextValid = () => { try { browser.runtime.getURL(''); return true; } catch { return false; } }; + + let failures = 0; + const intervalID = setInterval(() => { + failures = isExtensionContextValid() ? 0 : failures + 1; + if (failures >= 5 && !document.getElementById('xkit-modal')) { + showContextInvalidatedModal(); + clearInterval(intervalID); + } + }, 1000); + }; + const init = async function () { $('style.xkit, link.xkit').remove(); @@ -130,6 +150,8 @@ installedFeatures .filter(featureName => enabledFeatures.includes(featureName)) .forEach(runFeature); + + warnOnExtensionContextInvalidated(); }; const waitForReactLoaded = async function () { diff --git a/src/features/mass_deleter/index.js b/src/features/mass_deleter/index.js index 8f2b476f05..5873c6eee6 100644 --- a/src/features/mass_deleter/index.js +++ b/src/features/mass_deleter/index.js @@ -1,6 +1,6 @@ import { button, form, input, label, small, span } from '../../utils/dom.js'; import { megaEdit } from '../../utils/mega_editor.js'; -import { createBlogSpan, modalCancelButton, modalCompleteButton, showErrorModal, showModal } from '../../utils/modals.js'; +import { createBlogSpan, hideModal, modalCancelButton, modalCompleteButton, showErrorModal, showModal } from '../../utils/modals.js'; import { addSidebarItem, removeSidebarItem } from '../../utils/sidebar.js'; import { dateTimeFormat } from '../../utils/text_format.js'; import { apiFetch } from '../../utils/tumblr_helpers.js'; @@ -131,7 +131,8 @@ const deleteDrafts = async function ({ blogName, before }) { 'Refresh the page to see the result.', ], buttons: [ - button({ class: 'blue', click: () => location.reload() }, ['Refresh']), + button({ click: hideModal }, ['Close']), + button({ class: 'blue', click: () => location.reload() }, ['Refresh Now']), ], }); }; @@ -225,7 +226,8 @@ const clearQueue = async function ({ blogName }) { 'Refresh the page to see the result.', ], buttons: [ - button({ class: 'blue', click: () => location.reload() }, ['Refresh']), + button({ click: hideModal }, ['Close']), + button({ class: 'blue', click: () => location.reload() }, ['Refresh Now']), ], }); }; diff --git a/src/features/mass_privater/index.js b/src/features/mass_privater/index.js index 671e65c6fb..2980bb5716 100644 --- a/src/features/mass_privater/index.js +++ b/src/features/mass_privater/index.js @@ -236,7 +236,7 @@ const privatePosts = async ({ uuid, name, tags, before }) => { ], buttons: [ dom('button', null, { click: hideModal }, ['Close']), - dom('button', { class: 'blue' }, { click: () => location.reload() }, ['Refresh']), + dom('button', { class: 'blue' }, { click: () => location.reload() }, ['Refresh Now']), ], }); }; diff --git a/src/utils/modals.js b/src/utils/modals.js index 6c5ffdc846..e8a853fc52 100644 --- a/src/utils/modals.js +++ b/src/utils/modals.js @@ -72,5 +72,19 @@ export const withModalOnError = func => } }; +export const showContextInvalidatedModal = () => + showModal({ + title: 'XKit Rewritten has become unloaded.', + message: [ + 'If this is unexpected, this is likely due to your browser automatically applying an XKit version update.', + '\n\n', + 'Outdated XKit modifications will be updated/removed after you refresh this Tumblr tab.', + ], + buttons: [ + dom('button', null, { click: hideModal }, ['Close']), + dom('button', { class: 'blue' }, { click: () => location.reload() }, ['Refresh Now']), + ], + }); + export const createTagSpan = tag => dom('span', { class: 'xkit-modal-tag' }, null, [tag]); export const createBlogSpan = name => dom('span', { class: 'xkit-modal-blog' }, null, [name]);