From 033573e086ce14a12d694aab87700874c182860d Mon Sep 17 00:00:00 2001 From: MachineMitch21 Date: Thu, 19 Mar 2026 20:46:24 -0400 Subject: [PATCH 1/4] Prevent context menu options for tabs in focus mode Fixes #2643 --- js/browserUI.js | 11 ++++++++ js/webviewMenu.js | 66 ++++++++++++++++++++++++++++------------------- 2 files changed, 51 insertions(+), 26 deletions(-) diff --git a/js/browserUI.js b/js/browserUI.js index 05bba6a27..380d901b8 100644 --- a/js/browserUI.js +++ b/js/browserUI.js @@ -39,6 +39,17 @@ function addTab (tabId = tabs.add(), options = {}) { * The current tab is empty, and the new tab has a URL */ + if (focusMode.enabled()) { + /** + * Introduced with -> https://github.com/minbrowser/min/issues/2643 + * If the user has managed to get into this logic, we should just disallow and return + * Last ditch effort to prevent tab from being created in focus mode... + * + * i.e. --> User is using the middle mouse button to click on a link + */ + return + } + if (!options.openInBackground && !tabs.get(tabs.getSelected()).url && ((!tabs.get(tabs.getSelected()).private && tabs.get(tabId).private) || tabs.get(tabId).url)) { destroyTab(tabs.getSelected()) } diff --git a/js/webviewMenu.js b/js/webviewMenu.js index 3e85be9d9..d837f1be2 100644 --- a/js/webviewMenu.js +++ b/js/webviewMenu.js @@ -7,6 +7,7 @@ const userscripts = require('userscripts.js') const settings = require('util/settings/settings.js') const pageTranslations = require('pageTranslations.js') const PasswordManagers = require('passwordManager/passwordManager.js') +const focusMode = require('./focusMode') const remoteMenu = require('remoteMenuRenderer.js') @@ -82,22 +83,28 @@ const webviewMenu = { } ] - if (!currentTab.private) { + if (!focusMode.enabled()) { + /** + * https://github.com/minbrowser/min/issues/2643 + * Users should not see open in new tab in any capacity in the context menu while in focus mode + */ + if (!currentTab.private) { + linkActions.push({ + label: l('openInNewTab'), + click: function () { + browserUI.addTab(tabs.add({ url: link }), { enterEditMode: false, openInBackground: openInBackground }) + } + }) + } + linkActions.push({ - label: l('openInNewTab'), + label: l('openInNewPrivateTab'), click: function () { - browserUI.addTab(tabs.add({ url: link }), { enterEditMode: false, openInBackground: openInBackground }) + browserUI.addTab(tabs.add({ url: link, private: true }), { enterEditMode: false, openInBackground: openInBackground }) } }) } - linkActions.push({ - label: l('openInNewPrivateTab'), - click: function () { - browserUI.addTab(tabs.add({ url: link, private: true }), { enterEditMode: false, openInBackground: openInBackground }) - } - }) - linkActions.push({ label: l('saveLinkAs'), click: function () { @@ -121,29 +128,36 @@ const webviewMenu = { } ] - imageActions.push({ - label: l('viewImage'), - click: function () { - webviews.update(tabs.getSelected(), mediaURL) + if (!focusMode.enabled()) { + /** + * https://github.com/minbrowser/min/issues/2643 + * Users can get stuck viewing an image while in focus mode because they can't go back or exit the tab + * And users shouldn't be able to open tabs in any capacity while in focus mode + */ + imageActions.push({ + label: l('viewImage'), + click: function () { + webviews.update(tabs.getSelected(), mediaURL) + } + }) + + if (!currentTab.private) { + imageActions.push({ + label: l('openImageInNewTab'), + click: function () { + browserUI.addTab(tabs.add({ url: mediaURL }), { enterEditMode: false, openInBackground: openInBackground }) + } + }) } - }) - - if (!currentTab.private) { + imageActions.push({ - label: l('openImageInNewTab'), + label: l('openImageInNewPrivateTab'), click: function () { - browserUI.addTab(tabs.add({ url: mediaURL }), { enterEditMode: false, openInBackground: openInBackground }) + browserUI.addTab(tabs.add({ url: mediaURL, private: true }), { enterEditMode: false, openInBackground: openInBackground }) } }) } - imageActions.push({ - label: l('openImageInNewPrivateTab'), - click: function () { - browserUI.addTab(tabs.add({ url: mediaURL, private: true }), { enterEditMode: false, openInBackground: openInBackground }) - } - }) - imageActions.push({ label: l('saveImageAs'), click: function () { From 0341c4776f5ae359c0f01ec89fdb9fdab181bf6f Mon Sep 17 00:00:00 2001 From: MachineMitch21 Date: Thu, 19 Mar 2026 22:27:46 -0400 Subject: [PATCH 2/4] Do tabs.add() later in js/browserUI.js addTab() After exploring middle click behavior more, it's apparent it's baked into electron. So, in order to make sure we're not doing any default addTab() behavior, tabId must be undefined by default until we determine the user is not in focus mode. --- js/browserUI.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/js/browserUI.js b/js/browserUI.js index 380d901b8..3900ce2c9 100644 --- a/js/browserUI.js +++ b/js/browserUI.js @@ -32,7 +32,7 @@ options options.enterEditMode - whether to enter editing mode when the tab is created. Defaults to true. options.openInBackground - whether to open the tab without switching to it. Defaults to false. */ -function addTab (tabId = tabs.add(), options = {}) { +function addTab (tabId = undefined, options = {}) { /* adding a new tab should destroy the current one if either: * The current tab is an empty, non-private tab, and the new tab is private @@ -50,6 +50,9 @@ function addTab (tabId = tabs.add(), options = {}) { return } + // If tabId is undefined, and we're not in focus mode, then do true initialization of new tab and get id now... + tabId = !tabId ? tabs.add() : tabId; + if (!options.openInBackground && !tabs.get(tabs.getSelected()).url && ((!tabs.get(tabs.getSelected()).private && tabs.get(tabId).private) || tabs.get(tabId).url)) { destroyTab(tabs.getSelected()) } From f839ab6d057e5b2b58252f6b6bddb9c697959834 Mon Sep 17 00:00:00 2001 From: MachineMitch21 Date: Sun, 12 Apr 2026 12:45:28 -0400 Subject: [PATCH 3/4] Tighten strictness of tab context menu in focus mode --- js/navbar/tabContextMenu.js | 82 ++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/js/navbar/tabContextMenu.js b/js/navbar/tabContextMenu.js index 834cb6a9c..0a331a6ad 100644 --- a/js/navbar/tabContextMenu.js +++ b/js/navbar/tabContextMenu.js @@ -3,43 +3,57 @@ const browserUI = require('browserUI.js') const webviews = require('webviews.js') const readerView = require('readerView.js') const urlParser = require('util/urlParser.js') +const focusMode = require('../focusMode.js') const tabContextMenu = { show: function (tabId) { - const tabMenu = [ - [ - { - label: l('appMenuDuplicateTab'), - click: function () { - const sourceTab = tabs.get(tabId) - // strip tab id so that a new one is generated - const newTab = tabs.add({ ...sourceTab, id: undefined }) - - browserUI.addTab(newTab, { enterEditMode: false }) - } - }, - { - label: l('tabMenuNewWindow'), - click: function () { - // insert after current task - let index - if (tasks.getSelected()) { - index = tasks.getIndex(tasks.getSelected().id) + 1 - } - const newTask = tasks.get(tasks.add({}, index)) - - const targetTab = tabs.get(tabId) - tabs.destroy(targetTab.id) - - newTask.tabs.add(targetTab) - - ipc.send('newWindow', { initialTask: newTask.id }) - - browserUI.switchToTask(tasks.getSelected().id) - } - } - ] - ] + const tabMenu = [[]] + + /** + * https://github.com/minbrowser/min/issues/2643 + * + * Users should not be able to duplicate tabs or open new windows in focus mode. + * Prior to this, users would be able to duplicate tabs without actually creating the view for them. + * So, as a consequence, when the tabMenuNewWindow context menu option was clicked, + * those duplicated tabs from before would all aggregate through the `viewManager.createView` logic. + * Then, all of the priorly duplicated tabs would suddenly appear. + */ + if (!focusMode.enabled()) { + tabMenu = [ + [ + { + label: l('appMenuDuplicateTab'), + click: function () { + const sourceTab = tabs.get(tabId) + // strip tab id so that a new one is generated + const newTab = tabs.add({ ...sourceTab, id: undefined }) + + browserUI.addTab(newTab, { enterEditMode: false }) + } + }, + { + label: l('tabMenuNewWindow'), + click: function () { + // insert after current task + let index + if (tasks.getSelected()) { + index = tasks.getIndex(tasks.getSelected().id) + 1 + } + const newTask = tasks.get(tasks.add({}, index)) + + const targetTab = tabs.get(tabId) + tabs.destroy(targetTab.id) + + newTask.tabs.add(targetTab) + + ipc.send('newWindow', { initialTask: newTask.id }) + + browserUI.switchToTask(tasks.getSelected().id) + } + } + ] + ] + } if (tabs.get(tabId).url && (readerView.isReader(tabId) || !urlParser.isInternalURL(tabs.get(tabId).url))) { if (!readerView.isReader(tabId)) { From e963d99cf6b7d8d2e4d3a83e8b6dbd38cebcdcb8 Mon Sep 17 00:00:00 2001 From: MachineMitch21 Date: Sun, 12 Apr 2026 13:03:26 -0400 Subject: [PATCH 4/4] Previous commit broke tab context menu when not in focus mode --- js/navbar/tabContextMenu.js | 62 +++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/js/navbar/tabContextMenu.js b/js/navbar/tabContextMenu.js index 0a331a6ad..c81a5d901 100644 --- a/js/navbar/tabContextMenu.js +++ b/js/navbar/tabContextMenu.js @@ -19,40 +19,36 @@ const tabContextMenu = { * Then, all of the priorly duplicated tabs would suddenly appear. */ if (!focusMode.enabled()) { - tabMenu = [ - [ - { - label: l('appMenuDuplicateTab'), - click: function () { - const sourceTab = tabs.get(tabId) - // strip tab id so that a new one is generated - const newTab = tabs.add({ ...sourceTab, id: undefined }) - - browserUI.addTab(newTab, { enterEditMode: false }) - } - }, - { - label: l('tabMenuNewWindow'), - click: function () { - // insert after current task - let index - if (tasks.getSelected()) { - index = tasks.getIndex(tasks.getSelected().id) + 1 - } - const newTask = tasks.get(tasks.add({}, index)) - - const targetTab = tabs.get(tabId) - tabs.destroy(targetTab.id) - - newTask.tabs.add(targetTab) - - ipc.send('newWindow', { initialTask: newTask.id }) - - browserUI.switchToTask(tasks.getSelected().id) - } + tabMenu[0].push({ + label: l('appMenuDuplicateTab'), + click: function () { + const sourceTab = tabs.get(tabId) + // strip tab id so that a new one is generated + const newTab = tabs.add({ ...sourceTab, id: undefined }) + + browserUI.addTab(newTab, { enterEditMode: false }) + } + }) + tabMenu[0].push({ + label: l('tabMenuNewWindow'), + click: function () { + // insert after current task + let index + if (tasks.getSelected()) { + index = tasks.getIndex(tasks.getSelected().id) + 1 } - ] - ] + const newTask = tasks.get(tasks.add({}, index)) + + const targetTab = tabs.get(tabId) + tabs.destroy(targetTab.id) + + newTask.tabs.add(targetTab) + + ipc.send('newWindow', { initialTask: newTask.id }) + + browserUI.switchToTask(tasks.getSelected().id) + } + }) } if (tabs.get(tabId).url && (readerView.isReader(tabId) || !urlParser.isInternalURL(tabs.get(tabId).url))) {