├── .gitignore
├── icons
└── icon-128.png
├── zipForStore.sh
├── screenshots
├── screenshot.png
├── screenshot-new.png
├── large_promo_tile.png
├── promo_tile_orig.png
├── small_promo_tile.png
├── marquee_promo_tile.png
├── chrome_web_store_button.png
└── zoom_chrome_ext_trailer.mov
├── PRIVACY_POLICY.md
├── LICENSE
├── README.md
├── src
├── content.css
├── background.js
└── content.js
├── chrome-extension-store.md
└── manifest.json
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | store.zip
--------------------------------------------------------------------------------
/icons/icon-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChromeAdmin/meetings-page-auto-closer-for-zoom/HEAD/icons/icon-128.png
--------------------------------------------------------------------------------
/zipForStore.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | rm store.zip
3 | zip -R store.zip 'src/*' 'icons/*' 'manifest.json' 'LICENSE' 'README.md'
--------------------------------------------------------------------------------
/screenshots/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChromeAdmin/meetings-page-auto-closer-for-zoom/HEAD/screenshots/screenshot.png
--------------------------------------------------------------------------------
/screenshots/screenshot-new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChromeAdmin/meetings-page-auto-closer-for-zoom/HEAD/screenshots/screenshot-new.png
--------------------------------------------------------------------------------
/screenshots/large_promo_tile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChromeAdmin/meetings-page-auto-closer-for-zoom/HEAD/screenshots/large_promo_tile.png
--------------------------------------------------------------------------------
/screenshots/promo_tile_orig.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChromeAdmin/meetings-page-auto-closer-for-zoom/HEAD/screenshots/promo_tile_orig.png
--------------------------------------------------------------------------------
/screenshots/small_promo_tile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChromeAdmin/meetings-page-auto-closer-for-zoom/HEAD/screenshots/small_promo_tile.png
--------------------------------------------------------------------------------
/screenshots/marquee_promo_tile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChromeAdmin/meetings-page-auto-closer-for-zoom/HEAD/screenshots/marquee_promo_tile.png
--------------------------------------------------------------------------------
/screenshots/chrome_web_store_button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChromeAdmin/meetings-page-auto-closer-for-zoom/HEAD/screenshots/chrome_web_store_button.png
--------------------------------------------------------------------------------
/screenshots/zoom_chrome_ext_trailer.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChromeAdmin/meetings-page-auto-closer-for-zoom/HEAD/screenshots/zoom_chrome_ext_trailer.mov
--------------------------------------------------------------------------------
/PRIVACY_POLICY.md:
--------------------------------------------------------------------------------
1 | # meetings-page-auto-closer-for-zoom
2 |
3 | # Privacy Policy
4 |
5 | ## - __We don't have any servers.__
6 | ## - __No data leaves your computer.__
7 | ## - __We don't send or transmit any data to anywhere.__
8 | ## - __All your data belongs to you, we don't want it.__
9 |
10 |
11 | # So how does it work?
12 | ## All the data is securely processed inside the browser in an _[Isolated World](https://developer.chrome.com/extensions/content_scripts#isolated_world)_. With no data being transmitted outside the browser.
13 |
14 |
15 |
16 | ### So, in other words
17 | - Complete Privacy
18 | - No ads
19 | - No analytics
20 | - No data collection
21 |
22 | #### Therefore, we are HIPAA and GDPR Compliant.
23 |
24 | #### It's that simple :)
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Github User: ChromeAdmin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # meetings-page-auto-closer-for-zoom
2 |
3 | Automatically closes the page used to launch Zoom meetings and restores focus to the tab you were on beforehand. Supports pages launched by Zoom and ZoomGov. Easily change the countdown time by clicking one of the offered alternate times in blue.
4 |
5 | ## Safest extension. No Permissions Needed.
6 |
7 | Use Zoom for meetings? Then this extension will keep your Chrome running fast and smooth by automatically closing the page used to launch Zoom meetings after you've joined and restoring focus to the tab you were on beforehand.
8 |
9 | The most user friendly Redirect Page Closer you'll find in the store that uses the least permissions while giving you the ability to cancel the auto close timer. We natively blend in with the Zoom UI for a seamless experience. Auto closes the Zoom tab after joining the meeting.
10 |
11 | Complete privacy. Contains no analytics. Zero dependencies.
12 |
[See our Privacy Policy](PRIVACY_POLICY.md)
13 |
This extension is HIPAA and GDPR compliant.
14 |
15 | [](https://chrome.google.com/webstore/detail/meetings-page-auto-closer/pbgidoglkjhfgjhalbbiiahdlokjcplb)
16 |
17 | [](https://chrome.google.com/webstore/detail/meetings-page-auto-closer/pbgidoglkjhfgjhalbbiiahdlokjcplb)
18 |
19 |
20 | ## Test Urls
21 | - https://zoom.us/test
22 | - https://zoom.us/postattendee
23 | - https://zoom.us/wc/leave
24 |
25 | ## Notices
26 | This extension is not affliated, authorized by, endorsed by, or produced by Zoom Video Communications.
27 |
ZOOM is a trademark of Zoom Video Communications, Inc.
28 |
All other trademarks are the property of their respective holders.
29 |
--------------------------------------------------------------------------------
/src/content.css:
--------------------------------------------------------------------------------
1 | .meetings-page-auto-closer-for-zoom-wrapper {
2 | position: absolute;
3 | margin: auto;
4 | left: 0;
5 | right: 0;
6 | /* top: 100px; */
7 | /* top: 8px; */
8 | top: 0;
9 | /* Because we added padding, we need to skoot back to the top */
10 | z-index: 999;
11 | width: fit-content;
12 | }
13 |
14 | .meetings-page-auto-closer-for-zoom-wrapper .meetings-page-auto-closer-for-zoom-main-pop-over {
15 | padding: 6px;
16 | padding-left: 10px;
17 | padding-right: 10px;
18 | text-align: center;
19 | color: #3a3c3e;
20 | font-size: 18px;
21 | font-weight: 400;
22 | text-shadow: 0 0 2px white, 0 0 4px white, 0 0 6px snow, 0 0 10px snow;
23 | background: hsla(0, 0%, 100%, 90%);
24 | box-shadow: 0px 1px 10px 1px rgba(0, 0, 0, 0.67);
25 | border-radius: 4px;
26 | }
27 |
28 | .meetings-page-auto-closer-for-zoom-wrapper .meetings-page-auto-closer-for-zoom-main-pop-over .meetings-page-auto-closer-for-zoom-countdown-text {
29 | margin-bottom: 6px;
30 | }
31 |
32 | .meetings-page-auto-closer-for-zoom-wrapper .meetings-page-auto-closer-for-zoom-main-pop-over .meetings-page-auto-closer-for-zoom-stop-link {
33 | cursor: pointer;
34 | font-size: 16px;
35 | padding: 4px;
36 | }
37 |
38 | .meetings-page-auto-closer-for-zoom-wrapper .meetings-page-auto-closer-for-zoom-main-pop-over .meetings-page-auto-closer-for-zoom-close-now-btn {
39 | cursor: pointer;
40 | font-weight: bold;
41 | padding: 4px;
42 | font-size: 16px;
43 | margin-left: 36px;
44 | }
45 |
46 | .meetings-page-auto-closer-for-zoom-wrapper .meetings-page-auto-closer-for-zoom-settings-menu {
47 | margin-top: 6px;
48 | padding: 6px;
49 | padding-left: 10px;
50 | padding-right: 10px;
51 | text-align: center;
52 | color: #1e1e1f;
53 | font-size: 12px;
54 | font-weight: 400;
55 | background: rgb(255 240 178 / 80%);
56 | box-shadow: 0px 1px 5px 1px rgba(0, 0, 0, 0.33);
57 | border-radius: 2px;
58 | }
59 |
60 | .meetings-page-auto-closer-for-zoom-wrapper .meetings-page-auto-closer-for-zoom-settings-menu .meetings-page-auto-closer-for-zoom-settings-option {
61 | cursor: pointer;
62 | font-size: 12px;
63 | padding: 1px;
64 | }
65 |
--------------------------------------------------------------------------------
/chrome-extension-store.md:
--------------------------------------------------------------------------------
1 | # chrome-extension-store
2 | ## Product details
3 | ### Description
4 | Tired of those lingering redirect tabs? Close them automatically! Works with popular platforms like Zoom! This extension will keep your Chrome running fast and smooth by automatically closing the page used to launch Zoom meetings after you've joined and restores focus to the tab you were on beforehand.
5 |
6 | The most user friendly Redirect Closer you'll find in the store that uses the least permissions while giving you the ability to cancel the auto close timer. We natively blend in with the Zoom UI for a seamless experience. This extension Auto closes the Zoom tab after joining the meeting.
7 |
8 | Complete privacy. Contains no analytics. Zero dependencies.
9 | This extension is HIPAA and GDPR compliant.
10 |
11 | Experiencing issues? Please report them here: https://forms.gle/Y64QCYkRfFd2qVXm7
12 |
13 | Fully open source, safe, and secure:
14 | https://github.com/ChromeAdmin/meetings-page-auto-closer-for-zoom
15 |
16 | Privacy Policy:
17 | https://github.com/ChromeAdmin/meetings-page-auto-closer-for-zoom/blob/master/PRIVACY_POLICY.md
18 |
19 | Notices:
20 | This extension is not affiliated, authorized by, endorsed by, or produced by Zoom Video Communications.
21 | ZOOM is a trademark of Zoom Video Communications, Inc.
22 | All other trademarks are the property of their respective holders.
23 |
24 | Changelog:
25 | Last updated to allow easier closing and configurable close timer.
26 |
27 | ### Category
28 | Productivity
29 |
30 | ## Graphic Assets
31 | ### Promo Video
32 | https://www.youtube.com/watch?v=LVmwztcuIqQ
33 |
34 | ## Additional Fields
35 | ### Official URL
36 | chromeadmin.com
37 | ### Homepage Url
38 | https://github.com/ChromeAdmin/meetings-page-auto-closer-for-zoom
39 | ### Support URL
40 | https://forms.gle/Y64QCYkRfFd2qVXm7
41 |
42 |
43 | ## Privacy Practices
44 | ### Single purpose
45 | Automatically closes the page used to launch Zoom meetings and restores focus to the tab you were on beforehand. Supports pages launched by Zoom and ZoomGov.
46 | ### Permission justification
47 | This extension is limited to only run on specific zoom.us and zoomgov.com pages that are shown after joining a meeting, because those are the pages that we show to countdown timer on.
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/src/background.js:
--------------------------------------------------------------------------------
1 | // Background script
2 | const windowToLastActiveTabIdsMap = {}
3 |
4 | function getLastActiveTabIdsListForWindowId(windowId) {
5 | if (!windowToLastActiveTabIdsMap[`wId-${windowId}`]) {
6 | windowToLastActiveTabIdsMap[`wId-${windowId}`] = [];
7 | }
8 | return windowToLastActiveTabIdsMap[`wId-${windowId}`];
9 | }
10 |
11 | function addTabToWindowMap(windowId, tabId) {
12 | const lastActiveTabIdsList = getLastActiveTabIdsListForWindowId(windowId);
13 | //Remove the tabId from the last active if it exists
14 | const index = lastActiveTabIdsList.indexOf(tabId);
15 | if (index > -1) {
16 | lastActiveTabIdsList.splice(index, 1);
17 | }
18 | //Insert the tabId at the end
19 | lastActiveTabIdsList.push(tabId);
20 |
21 | //If we've gone over our self-imposed size then delete the oldest added tabId
22 | if (lastActiveTabIdsList.length > 5) {
23 | lastActiveTabIdsList.shift();
24 | }
25 | }
26 |
27 | function focusTab(tabId) {
28 | const updateProperties = { active: true };
29 | chrome.tabs.update(tabId, updateProperties, (tab) => { });
30 | }
31 |
32 |
33 | chrome.tabs.onActivated.addListener((activeInfo) => {
34 | // console.log(`windowId: ${activeInfo.windowId} tabId:${activeInfo.tabId}`);
35 | addTabToWindowMap(activeInfo.windowId, activeInfo.tabId);
36 | });
37 |
38 | chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
39 | if (!message.pleaseCloseThisTab) { return; }
40 |
41 | const windowId = sender.tab.windowId;
42 | const tabId = sender.tab.id;
43 | const lastActiveTabIdsList = getLastActiveTabIdsListForWindowId(windowId);
44 | if (lastActiveTabIdsList.length >= 2) { //There need to be at least 2 tabs in our window's history
45 | const lastActiveTabId = lastActiveTabIdsList[lastActiveTabIdsList.length - 1];
46 | const activeBeforeLastTabId = lastActiveTabIdsList[lastActiveTabIdsList.length - 2];
47 | if (tabId === lastActiveTabId) {
48 | // This is a case where the zoom tab we are about to close
49 | // is the lastActiveTabId for this window. So we will change
50 | // the focus to the tab previously active in this window.
51 | focusTab(activeBeforeLastTabId);
52 | console.log('MPACFZ: Recovered the active tab before zoom.');
53 | }
54 | }
55 |
56 | chrome.tabs.remove(tabId);
57 | });
58 |
59 | console.log(`MPACFZ: meetings-page-auto-closer-for-zoom loaded.`)
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Meetings Page Auto Closer for Zoom",
3 | "description": "Automatically closes the page opened by Zoom to launch meetings and restores focus to the tab you were on before opened.",
4 | "version": "0.3.1",
5 | "manifest_version": 3,
6 | "homepage_url": "https://github.com/ChromeAdmin/meetings-page-auto-closer-for-zoom",
7 | "icons": {
8 | "16": "icons/icon-128.png",
9 | "48": "icons/icon-128.png",
10 | "128": "icons/icon-128.png"
11 | },
12 | "permissions": [],
13 | "background": {
14 | "service_worker": "src/background.js"
15 | },
16 | "content_scripts": [
17 | {
18 | "run_at": "document_start",
19 | "matches": [
20 | "*://*.zoom.us/a/*",
21 | "*://*.zoom.us/b/*",
22 | "*://*.zoom.us/c/*",
23 | "*://*.zoom.us/d/*",
24 | "*://*.zoom.us/e/*",
25 | "*://*.zoom.us/f/*",
26 | "*://*.zoom.us/g/*",
27 | "*://*.zoom.us/h/*",
28 | "*://*.zoom.us/i/*",
29 | "*://*.zoom.us/j/*",
30 | "*://*.zoom.us/k/*",
31 | "*://*.zoom.us/l/*",
32 | "*://*.zoom.us/m/*",
33 | "*://*.zoom.us/n/*",
34 | "*://*.zoom.us/o/*",
35 | "*://*.zoom.us/p/*",
36 | "*://*.zoom.us/q/*",
37 | "*://*.zoom.us/r/*",
38 | "*://*.zoom.us/s/*",
39 | "*://*.zoom.us/t/*",
40 | "*://*.zoom.us/u/*",
41 | "*://*.zoom.us/v/*",
42 | "*://*.zoom.us/w/*",
43 | "*://*.zoom.us/x/*",
44 | "*://*.zoom.us/y/*",
45 | "*://*.zoom.us/z/*",
46 | "*://*.zoom.us/postattendee*",
47 | "*://*.zoom.us/wc/leave*",
48 | "*://*.zoomgov.com/a/*",
49 | "*://*.zoomgov.com/b/*",
50 | "*://*.zoomgov.com/c/*",
51 | "*://*.zoomgov.com/d/*",
52 | "*://*.zoomgov.com/e/*",
53 | "*://*.zoomgov.com/f/*",
54 | "*://*.zoomgov.com/g/*",
55 | "*://*.zoomgov.com/h/*",
56 | "*://*.zoomgov.com/i/*",
57 | "*://*.zoomgov.com/j/*",
58 | "*://*.zoomgov.com/k/*",
59 | "*://*.zoomgov.com/l/*",
60 | "*://*.zoomgov.com/m/*",
61 | "*://*.zoomgov.com/n/*",
62 | "*://*.zoomgov.com/o/*",
63 | "*://*.zoomgov.com/p/*",
64 | "*://*.zoomgov.com/q/*",
65 | "*://*.zoomgov.com/r/*",
66 | "*://*.zoomgov.com/s/*",
67 | "*://*.zoomgov.com/t/*",
68 | "*://*.zoomgov.com/u/*",
69 | "*://*.zoomgov.com/v/*",
70 | "*://*.zoomgov.com/w/*",
71 | "*://*.zoomgov.com/x/*",
72 | "*://*.zoomgov.com/y/*",
73 | "*://*.zoomgov.com/z/*",
74 | "*://*.zoomgov.com/postattendee*",
75 | "*://*.zoomgov.com/wc/leave*"
76 | ],
77 | "js": [
78 | "src/content.js"
79 | ],
80 | "css": [
81 | "src/content.css"
82 | ]
83 | }
84 | ]
85 | }
--------------------------------------------------------------------------------
/src/content.js:
--------------------------------------------------------------------------------
1 | const intervalRateMs = 1000;
2 | const maxCountdownStartTimeMs = 35 * 1000;
3 | const minCountdownStartTimeMs = 5 * 1000;
4 |
5 | const cssClassName_Wrapper = `meetings-page-auto-closer-for-zoom-wrapper`;
6 | const cssClassName_MainPopOver = `meetings-page-auto-closer-for-zoom-main-pop-over`;
7 | const cssClassName_CountdownText = `meetings-page-auto-closer-for-zoom-countdown-text`;
8 | const cssClassName_CloseNowBtn = `meetings-page-auto-closer-for-zoom-close-now-btn`;
9 | const cssClassName_StopLink = `meetings-page-auto-closer-for-zoom-stop-link`;
10 |
11 | const cssClassName_SettingsMenu = `meetings-page-auto-closer-for-zoom-settings-menu`;
12 | const cssClassName_SettingsOption = `meetings-page-auto-closer-for-zoom-settings-option`;
13 |
14 | const localStorageKey_CountdownStartTimeMs = `b9d55053-5a15-4b65-98ce-73711e1d83f9`;
15 |
16 | function log(text) {
17 | console.log(`MPACFZ: ${text}`);
18 | }
19 |
20 | log('loaded...');
21 |
22 | let timeTillCloseMs = getCountdownStartTimeMs();
23 |
24 | function getCountdownStartTimeMs() {
25 | const defaultStartTimeMs = 21 * 1000;
26 | let startTimeMs = defaultStartTimeMs;
27 | try {
28 | startTimeMs = Number(localStorage.getItem(localStorageKey_CountdownStartTimeMs));
29 | } catch (e) {
30 | console.error(e);
31 | }
32 | if (!startTimeMs || startTimeMs <= minCountdownStartTimeMs || startTimeMs > maxCountdownStartTimeMs) {
33 | setCountdownStartTimeMs(defaultStartTimeMs); // Overwrite to self-correct
34 | startTimeMs = defaultStartTimeMs;
35 | }
36 | return startTimeMs;
37 | }
38 |
39 | function setCountdownStartTimeMs(startTimeMs) {
40 | localStorage.setItem(localStorageKey_CountdownStartTimeMs, startTimeMs);
41 | }
42 |
43 | function getWrapperEl() {
44 | return document.documentElement.querySelector(`.${cssClassName_Wrapper}`);
45 | }
46 |
47 | function countdownWithText(countdownTimeMs) {
48 | if (false) {//Used for freezing the countdown to debugging styling
49 | countdownTimeMs = getCountdownStartTimeMs();
50 | clearInterval(intervalId);
51 | }
52 |
53 | let wrapperEl = getWrapperEl();
54 |
55 | if (!wrapperEl) { // Lazy init the element
56 | wrapperEl = document.createElement('div');
57 | wrapperEl.classList.add(cssClassName_Wrapper);
58 | wrapperEl.innerHTML = `
59 |