From af258a03247dcb4b33efc23fcc6ebfba36645c43 Mon Sep 17 00:00:00 2001 From: marcustyphoon Date: Mon, 8 Jun 2026 17:33:02 -0700 Subject: [PATCH 1/6] show modal on chromium update/disable --- src/content_scripts/main.js | 23 +++++++++++++++++++++++ src/utils/modals.js | 14 ++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/content_scripts/main.js b/src/content_scripts/main.js index 8f5ed5653d..4cc464a922 100644 --- a/src/content_scripts/main.js +++ b/src/content_scripts/main.js @@ -107,6 +107,27 @@ 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 { showUnloadedModal } = await import(browser.runtime.getURL('/utils/modals.js')); + + const isExtensionContextValid = () => { try { browser.runtime.getURL(''); return true; } catch { return false; } }; + + let failures = 0; + while (true) { + failures = isExtensionContextValid() ? 0 : failures + 1; + if (failures >= 5 && !document.getElementById('xkit-modal')) { + showUnloadedModal(); + break; + } + await new Promise(resolve => setTimeout(resolve, 1000)); + } + }; + const init = async function () { $('style.xkit, link.xkit').remove(); @@ -130,6 +151,8 @@ installedFeatures .filter(featureName => enabledFeatures.includes(featureName)) .forEach(runFeature); + + warnOnExtensionContextInvalidated(); }; const waitForReactLoaded = async function () { diff --git a/src/utils/modals.js b/src/utils/modals.js index 6c5ffdc846..ce2fd085ab 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]); From 732a201c7640533e775e909ce41c46beee0a710a Mon Sep 17 00:00:00 2001 From: marcustyphoon Date: Mon, 8 Jun 2026 17:35:03 -0700 Subject: [PATCH 2/6] make refresh buttons consistent --- src/features/mass_deleter/index.js | 8 +++++--- src/features/mass_privater/index.js | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) 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']), ], }); }; From fc2a1df674097dad3bb1312b6a7236c8b108842a Mon Sep 17 00:00:00 2001 From: marcustyphoon Date: Mon, 8 Jun 2026 18:05:55 -0700 Subject: [PATCH 3/6] it is actually good if you commit your refactors --- src/content_scripts/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content_scripts/main.js b/src/content_scripts/main.js index 4cc464a922..7b0deb3e8b 100644 --- a/src/content_scripts/main.js +++ b/src/content_scripts/main.js @@ -113,7 +113,7 @@ * context javascript immediately. */ const warnOnExtensionContextInvalidated = async () => { - const { showUnloadedModal } = await import(browser.runtime.getURL('/utils/modals.js')); + const { warnOnExtensionContextInvalidated } = await import(browser.runtime.getURL('/utils/modals.js')); const isExtensionContextValid = () => { try { browser.runtime.getURL(''); return true; } catch { return false; } }; @@ -121,7 +121,7 @@ while (true) { failures = isExtensionContextValid() ? 0 : failures + 1; if (failures >= 5 && !document.getElementById('xkit-modal')) { - showUnloadedModal(); + warnOnExtensionContextInvalidated(); break; } await new Promise(resolve => setTimeout(resolve, 1000)); From 14828813936ad26b079a550d611158e067ea9ae4 Mon Sep 17 00:00:00 2001 From: marcustyphoon Date: Mon, 8 Jun 2026 18:07:28 -0700 Subject: [PATCH 4/6] it is actually even better if you copy paste the right string --- src/content_scripts/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content_scripts/main.js b/src/content_scripts/main.js index 7b0deb3e8b..dac78f132a 100644 --- a/src/content_scripts/main.js +++ b/src/content_scripts/main.js @@ -113,7 +113,7 @@ * context javascript immediately. */ const warnOnExtensionContextInvalidated = async () => { - const { warnOnExtensionContextInvalidated } = await import(browser.runtime.getURL('/utils/modals.js')); + const { showContextInvalidatedModal } = await import(browser.runtime.getURL('/utils/modals.js')); const isExtensionContextValid = () => { try { browser.runtime.getURL(''); return true; } catch { return false; } }; @@ -121,7 +121,7 @@ while (true) { failures = isExtensionContextValid() ? 0 : failures + 1; if (failures >= 5 && !document.getElementById('xkit-modal')) { - warnOnExtensionContextInvalidated(); + showContextInvalidatedModal(); break; } await new Promise(resolve => setTimeout(resolve, 1000)); From 7969bbb48e52f353c32e9e9afdf6bec49ed4efbc Mon Sep 17 00:00:00 2001 From: marcustyphoon Date: Tue, 9 Jun 2026 02:14:59 -0700 Subject: [PATCH 5/6] use setInterval Co-Authored-By: April Sylph <28949509+AprilSylph@users.noreply.github.com> --- src/content_scripts/main.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/content_scripts/main.js b/src/content_scripts/main.js index dac78f132a..750f137514 100644 --- a/src/content_scripts/main.js +++ b/src/content_scripts/main.js @@ -118,14 +118,13 @@ const isExtensionContextValid = () => { try { browser.runtime.getURL(''); return true; } catch { return false; } }; let failures = 0; - while (true) { + const intervalID = setInterval(() => { failures = isExtensionContextValid() ? 0 : failures + 1; if (failures >= 5 && !document.getElementById('xkit-modal')) { showContextInvalidatedModal(); - break; + clearInterval(intervalID); } - await new Promise(resolve => setTimeout(resolve, 1000)); - } + }, 1000); }; const init = async function () { From 21cf47c0b37cc6fb4e841ddc127ecebf76c79395 Mon Sep 17 00:00:00 2001 From: marcustyphoon Date: Thu, 11 Jun 2026 13:49:27 -0700 Subject: [PATCH 6/6] Apply suggested verbiage change from code review Co-authored-by: April Sylph <28949509+AprilSylph@users.noreply.github.com> --- src/utils/modals.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/modals.js b/src/utils/modals.js index ce2fd085ab..e8a853fc52 100644 --- a/src/utils/modals.js +++ b/src/utils/modals.js @@ -76,7 +76,7 @@ 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!', + '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.', ],