Skip to content

Commit

Permalink
Merge pull request #7 from sethcottle/threedotzero
Browse files Browse the repository at this point in the history
TabCloser 3
  • Loading branch information
sethcottle authored Jul 18, 2024
2 parents 7e4d43e + 03da4c9 commit 01a8deb
Show file tree
Hide file tree
Showing 23 changed files with 861 additions and 289 deletions.
Binary file modified Images/icon128.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Images/icon16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Images/icon48.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
178 changes: 68 additions & 110 deletions background.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,130 +9,88 @@
// TabCloser is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Please see the
// GNU General Public License for more details.
// GNU General Public License for more details.

const debug = false;
const debug = false; // Set to true for debugging

const predefinedUrlPatterns = [
{
label: ' Asana',
pattern: '^https?://app\\.asana\\.com/-/desktop_app_link\\?.*',
},
{
label: ' AWS IAM Access Auth Success',
pattern: '^https://[a-z0-9-]+\\.awsapps\\.com/start/user-consent/login-success.html',
},
{
label: ' Discord Invites',
pattern: '^https?://discord\\.com/invite/',
},
{
label: ' Figma Files',
pattern: '^https?://(?:www\.)?figma\.com/file/',
},
{
label: ' Linear',
pattern: '^https?://linear\\.app/.*\\?noRedirect=1$',
},
{
label: ' Microsoft Teams',
pattern: '^https?://teams\\.microsoft\\.com/dl/launcher/.*',
},
{
label: ' Notion',
pattern: '^https?://www\\.notion\\.so/native/.*&deepLinkOpenNewTab=true',
},
{
label: ' Slack',
pattern: '^https?://(?!(app\\.slack\\.com|slack\\.com|api\\.slack\\.com|.*\\/(customize|account|apps)(\\/|$)|.*\\/home(\\/|$)))[a-z0-9-]+\\.slack\\.com/.*$',
},
{
label: ' Spotify',
pattern: '^https?://open\\.spotify\\.com',
},
{
label: ' VS Code Live Share',
pattern: '^https?://vscode\\.dev/liveshare',
},
{
label: ' Webex Joins',
pattern: '^https?://([a-z0-9-]+\\.)?webex\\.com/wbxmjs/joinservice',
},
{
label: ' Zoom Joins',
pattern: '^https?://([a-z0-9-]+\\.)?zoom\\.us/j/[^/]+#success$',
},
{ label: 'Asana', pattern: '^https?://app\\.asana\\.com/-/desktop_app_link\\?.*' },
{ label: 'AWS IAM Access Auth Success', pattern: '^https://[a-z0-9-]+\\.awsapps\\.com/start/user-consent/login-success.html' },
{ label: 'Discord Invites', pattern: '^https?://discord\\.com/invite/' },
{ label: 'Figma Design Files', pattern: '^https?://(?:www\.)?figma\.com/design/' },
{ label: 'Figjam Files', pattern: '^https?://(?:www\.)?figma\.com/board/' },
{ label: 'Figma Slide Files', pattern: '^https?://(?:www\.)?figma\.com/slides/' },
{ label: 'Linear', pattern: '^https?://linear\\.app/.*\\?noRedirect=1$' },
{ label: 'Microsoft Teams', pattern: '^https?://teams\\.microsoft\\.com/dl/launcher/.*' },
{ label: 'Notion', pattern: '^https?://www\\.notion\\.so/native/.*&deepLinkOpenNewTab=true' },
{ label: 'Slack', pattern: '^https?://(?!(app\\.slack\\.com|slack\\.com|api\\.slack\\.com|.*\\/(customize|account|apps)(\\/|$)|.*\\/home(\\/|$)))[a-z0-9-]+\\.slack\\.com/.*$' },
{ label: 'Spotify', pattern: '^https?://open\\.spotify\\.com' },
{ label: 'VS Code Live Share', pattern: '^https?://vscode\\.dev/liveshare' },
{ label: 'Webex Joins', pattern: '^https?://([a-z0-9-]+\\.)?webex\\.com/wbxmjs/joinservice' },
{ label: 'Zoom Joins', pattern: '^https?://([a-z0-9-]+\\.)?zoom\\.us/j/[^/]+#success$' },
];

function shouldCloseTab(url) {
return new Promise((resolve) => {
chrome.storage.sync.get(['disabledUrls'], ({ disabledUrls }) => {
if (!disabledUrls) {
disabledUrls = [];
}
const shouldClose = predefinedUrlPatterns.some(({ pattern }) => {
const regex = new RegExp(pattern, 'i');
return regex.test(url) && !disabledUrls.includes(pattern);
});
resolve(shouldClose);
});
async function shouldCloseTab(url) {
const { disabledUrls = [], customUrls = [] } = await chrome.storage.sync.get(['disabledUrls', 'customUrls']);

// Check predefined patterns
const shouldCloseDefault = predefinedUrlPatterns.some(({ pattern, label }) => {
const regex = new RegExp(pattern, 'i');
if (regex.test(url) && !disabledUrls.includes(pattern)) {
if (debug) console.log(`Should close (default): true (matched: ${label})`);
return true;
}
return false;
});

// Check custom URLs (exact literal match)
const shouldCloseCustom = customUrls.some(({ url: customUrl, enabled }) => {
if (enabled && url === customUrl) {
if (debug) console.log(`Should close (custom): true (matched: ${customUrl})`);
return true;
}
return false;
});

if (debug && !shouldCloseDefault && !shouldCloseCustom) {
console.log(`URL does not match any closing patterns: ${url}`);
}

return shouldCloseDefault || shouldCloseCustom;
}

async function checkTab(tab, interval) {
const shouldClose = await shouldCloseTab(tab.url);
if (shouldClose) {
try {
await new Promise((resolve, reject) => {
setTimeout(() => {
chrome.tabs.remove(tab.id, () => {
const err = chrome.runtime.lastError;
if (err) {
reject(err);
} else {
resolve();
}
});
}, interval * 1000);
});
} catch (error) {
console.log(`Error closing tab with id ${tab.id}:`, error.message);
async function checkAndCloseTab(tabId, changeInfo, tab) {
if (changeInfo.status === 'complete') {
if (debug) console.log(`Tab updated: ${tab.url}`);
const { interval = 15 } = await chrome.storage.sync.get(['interval']);

if (await shouldCloseTab(tab.url)) {
if (debug) console.log(`Scheduling tab for closure: ${tab.url}`);
setTimeout(async () => {
try {
await chrome.tabs.remove(tabId);
if (debug) console.log(`Closed tab: ${tab.url}`);
} catch (error) {
if (debug) console.error(`Error closing tab ${tab.url}: ${error.message}`);
}
}, interval * 1000);
}
}
}

function processTabs(tabs, index, interval) {
if (index >= tabs.length) {
return;
}
// Listen for tab updates
chrome.tabs.onUpdated.addListener(checkAndCloseTab);

const tab = tabs[index];
checkTab(tab, interval);
processTabs(tabs, index + 1, interval);
}
// Service Worker initialization
chrome.runtime.onInstalled.addListener(() => {
if (debug) console.log('TabCloser installed');
});

function runTabCloser() {
chrome.storage.sync.get(['interval'], ({ interval }) => {
interval = interval || 15;
if (debug) {
console.log('TabCloser interval:', interval);
// Debug logging for storage changes
if (debug) {
chrome.storage.onChanged.addListener((changes, areaName) => {
if (areaName === 'sync') {
console.log('Storage changes:', changes);
}
chrome.tabs.query({}, (tabs) => processTabs(tabs, 0, interval));
});

if (debug) {
chrome.storage.onChanged.addListener((changes, areaName) => {
if (areaName === 'sync') {
for (const key in changes) {
console.log(`Changed ${key}:`, changes[key]);
}
}
});
}
}

chrome.tabs.onCreated.addListener((tab) => {
setTimeout(runTabCloser, 5000);
});

runTabCloser();
1 change: 1 addition & 0 deletions icons/asana.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions icons/aws-iam.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions icons/code.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions icons/discord.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions icons/figma-design.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions icons/figma-figjam.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions icons/figma-slides.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 01a8deb

Please sign in to comment.