diff --git a/interface/lib/ads/activeAds.js b/interface/lib/ads/activeAds.js index 792cbbb..211b1e7 100644 --- a/interface/lib/ads/activeAds.js +++ b/interface/lib/ads/activeAds.js @@ -30,33 +30,32 @@ export const ActiveAds = Object.freeze([ "Raise money for charity every time you open a new browser tab. It's free and incredibly easy. Transform your tabs into a force for good in 30 seconds.", url: 'https://tab.gladly.io/cookieeditor/', supportedBrowsers: [Browsers.Chrome, Browsers.Edge, Browsers.Safari], - refreshDays: 80, + refreshDays: 90, startDate: new Date('2023/09/01'), - endDate: new Date('2024/09/01'), + endDate: new Date('2024/02/29'), }), new Ad({ - id: 'moosend', - text: 'Turn email into your ally with Moosend’s email marketing tools!', + id: 'tab-for-cause2', + text: 'Have 47+ tabs open? Try Tab for a Cause to raise money for non-profits', tooltip: - 'Manage your audience, segment it and use the data you collected to deliver messages that will make them click and convert! Start your journey today.', - url: 'https://trymoo.moosend.com/cookie-editor', - supportedBrowsers: Browsers.Any, - refreshDays: 100, - startDate: new Date('2023/11/01'), - endDate: new Date('2024/11/01'), + "Raise money for charity every time you open a new browser tab. It's free and incredibly easy. Transform your tabs into a force for good in 30 seconds.", + url: 'https://tab.gladly.io/cookieeditor/', + supportedBrowsers: [Browsers.Chrome, Browsers.Edge, Browsers.Safari], + refreshDays: 90, + startDate: new Date('2023/04/01'), + endDate: new Date('2025/09/01'), }), new Ad({ id: 'skillshare', - text: 'Join Skillshare Today and Get 30% Off Annual Membership.', - tooltip: - 'Get unlimited access to classes on illustration, photography, design, film, music, and more.', + text: 'Skillshare | Explore your creativity with thousands of hands‑on classes.', + tooltip: 'Join Skillshare Today and Get 30% Off Annual Membership.', url: 'https://skillshare.eqcm.net/Mmo4oM', supportedBrowsers: Browsers.Any, - refreshDays: 90, + refreshDays: 110, startDate: new Date('2023/10/21'), - endDate: new Date('2024/12/01'), + endDate: new Date('2025/05/01'), }), new Ad({ @@ -66,33 +65,33 @@ export const ActiveAds = Object.freeze([ 'Get NordVPN now to protect yourself online every day, wherever you are. Securely access apps, websites, and entertainment.', url: 'https://go.nordvpn.net/aff_c?offer_id=15&aff_id=93111&url_id=902', supportedBrowsers: Browsers.Any, - refreshDays: 105, + refreshDays: 120, startDate: new Date('2023/11/15'), - endDate: new Date('2024/12/01'), + endDate: new Date('2024/03/15'), }), new Ad({ id: 'nordvpn-deal', - text: 'Get 65% off the 2-year NordVPN plan + 3 months extra.', + text: "Don't miss a chance and grab a limited NordVPN deal!", tooltip: - 'Stay safer online with the leading VPN service. Detect malware during download. Block trackers and intrusive ads.', + 'Get NordVPN now to protect yourself online every day, wherever you are. Securely access apps, websites, and entertainment.', url: 'https://go.nordvpn.net/aff_c?offer_id=15&aff_id=93111&url_id=902', supportedBrowsers: Browsers.Any, - refreshDays: 105, - startDate: new Date('2023/10/01'), - endDate: new Date('2023/11/14'), + refreshDays: 120, + startDate: new Date('2024/03/16'), + endDate: new Date('2024/12/31'), }), new Ad({ id: 'aura', - text: 'Aura | Intelligent Digital Safety for the Whole Family', + text: 'Aura | #1 Rated Identity Theft Protection - Try Aura 14-days free.', tooltip: - 'Aura protects your identity, finances and sensitive data. All plans include a $1M insurance policy that covers eligible losses. Try Aura 14-days free.', + 'Aura protects your identity, finances and sensitive data. All plans include a $1M insurance policy that covers eligible losses.', url: 'https://aurainc.sjv.io/c/4869326/1835216/12398', supportedBrowsers: Browsers.Any, - refreshDays: 125, + refreshDays: 130, startDate: new Date('2023/10/07'), - endDate: new Date('2024/12/01'), + endDate: new Date('2025/02/01'), }), new Ad({ @@ -102,8 +101,42 @@ export const ActiveAds = Object.freeze([ 'Thousands of companies are collecting, aggregating, and trading your personal data without you knowing anything about it. Incogni makes them remove it so your data stays secure and private.', url: 'https://get.incogni.io/aff_c?offer_id=1150&aff_id=25909', supportedBrowsers: Browsers.Any, - refreshDays: 125, + refreshDays: 140, startDate: new Date('2023/10/07'), endDate: new Date('2024/12/01'), }), + + new Ad({ + id: 'incogni-code', + text: 'Incogni | Want to stop robocalls and spam emails today?', + tooltip: + 'Thousands of companies are collecting, aggregating, and trading your personal data without you knowing anything about it. Incogni makes them remove it so your data stays secure and private.', + url: 'https://get.incogni.io/aff_c?offer_id=1150&aff_id=25909', + supportedBrowsers: Browsers.Any, + refreshDays: 140, + startDate: new Date('2024/03/07'), + endDate: new Date('2024/12/01'), + }), + + new Ad({ + id: 'namecheap', + text: 'Namecheap | Get a .COM for just $5.98!', + tooltip: 'All domains for great prices. Prices are succeptible to change.', + url: 'https://namecheap.pxf.io/zNkAPe', + supportedBrowsers: Browsers.Any, + refreshDays: 130, + startDate: new Date('2024/03/14'), + endDate: new Date('2025/03/14'), + }), + + new Ad({ + id: 'curiosity-box', + text: 'Try the Curiosity Box by VSauce and get a FREE Lightyear Bottle!', + tooltip: "The world's best science toys by science legend, VSauce.", + url: 'https://the-curiosity-box.pxf.io/DKrYOo', + supportedBrowsers: Browsers.Any, + refreshDays: 100, + startDate: new Date('2024/03/14'), + endDate: new Date('2025/03/14'), + }), ]); diff --git a/interface/lib/options/options.js b/interface/lib/options/options.js index 425e1df..d46f813 100644 --- a/interface/lib/options/options.js +++ b/interface/lib/options/options.js @@ -16,6 +16,7 @@ export class Options { this.exportFormat = ExportFormats.Ask; this.extraInfo = ExtraInfos.Nothing; this.theme = Themes.Auto; + this.buttonBarTop = false; this.adsEnabled = true; } } diff --git a/interface/lib/optionsHandler.js b/interface/lib/optionsHandler.js index 5bde3f9..866cb7d 100644 --- a/interface/lib/optionsHandler.js +++ b/interface/lib/optionsHandler.js @@ -221,6 +221,22 @@ export class OptionsHandler extends EventEmitter { return false; } + /** + * Gets whether the button bar is displayed at the top of the page or not. + * @return {boolean} True if the button bar is on the top, otherwise false. + */ + getButtonBarTop() { + return this.options.buttonBarTop; + } + /** + * Sets whether the button bar is displayed at the top of the page or not. + * @param {boolean} buttonBarTop True if the button bar is on the top, otherwise false. + */ + setButtonBarTop(buttonBarTop) { + this.options.buttonBarTop = buttonBarTop; + this.saveOptions(); + } + /** * Gets whether ads are enabled or not. * @return {boolean} True if ads are enabled, otherwise false. diff --git a/interface/options/options.html b/interface/options/options.html index a22d3dd..66cae6c 100644 --- a/interface/options/options.html +++ b/interface/options/options.html @@ -102,6 +102,18 @@ automatically. + +
+ + +
+ When enabled, the main button bar will be placed at the top of the + interface instead of the bottom. +
+
diff --git a/interface/options/options.js b/interface/options/options.js index 58b6137..eb1af45 100644 --- a/interface/options/options.js +++ b/interface/options/options.js @@ -21,6 +21,7 @@ document.addEventListener('DOMContentLoaded', async (event) => { const exportFormatInput = document.getElementById('export-format'); const extraInfoInput = document.getElementById('extra-info'); const themeInput = document.getElementById('theme'); + const buttonBarTopInput = document.getElementById('button-bar-top'); const adsEnabledInput = document.getElementById('ads-enabled'); await optionHandler.loadOptions(); @@ -41,6 +42,7 @@ document.addEventListener('DOMContentLoaded', async (event) => { exportFormatInput.value = optionHandler.getExportFormat(); extraInfoInput.value = optionHandler.getExtraInfo(); themeInput.value = optionHandler.getTheme(); + buttonBarTopInput.checked = optionHandler.getButtonBarTop(); adsEnabledInput.checked = optionHandler.getAdsEnabled(); if (!browserDetector.isSafari()) { @@ -92,6 +94,12 @@ document.addEventListener('DOMContentLoaded', async (event) => { optionHandler.setTheme(themeInput.value); themeHandler.updateTheme(); }); + buttonBarTopInput.addEventListener('change', (event) => { + if (!event.isTrusted) { + return; + } + optionHandler.setButtonBarTop(buttonBarTopInput.checked); + }); adsEnabledInput.addEventListener('change', (event) => { if (!event.isTrusted) { return; diff --git a/interface/options/style.css b/interface/options/style.css index b2ebbcb..f4d7c9d 100644 --- a/interface/options/style.css +++ b/interface/options/style.css @@ -54,6 +54,7 @@ a:hover { .input-container { min-height: 2em; + margin-top: 5px; } .input-container input, @@ -101,7 +102,7 @@ a:hover { color: var(--secondary-text-color); font-size: 0.8em; padding: 1em; - padding-top: 2px; + padding-top: 4px; } .notice { diff --git a/interface/popup-mobile/style.css b/interface/popup-mobile/style.css index a77ad4a..32c74e3 100644 --- a/interface/popup-mobile/style.css +++ b/interface/popup-mobile/style.css @@ -521,6 +521,12 @@ label { user-select: none; overflow: hidden; } + +.button-bar-top .panel-section-footer { + border-top: none; + border-bottom: 1px solid rgba(0, 0, 0, 0.15); +} + .panel-section-footer-button { flex: 1 1; font-size: 18px; @@ -564,6 +570,10 @@ label { padding: 0 25px; } +.button-bar-top #notification-container { + bottom: 30px; +} + #notification { position: relative; display: inline-block; @@ -760,6 +770,17 @@ label { border-right: solid 15px transparent; } +.button-bar-top #export-menu { + top: 142px; + bottom: auto; +} +.button-bar-top #export-menu:after { + top: auto; + bottom: 100%; + border-top: none; + border-bottom: solid 10px var(--menu-surface-color); +} + #export-menu button { background-color: var(--menu-surface-color); color: var(--primary-text-color); diff --git a/interface/popup/cookie-list.js b/interface/popup/cookie-list.js index 9fddb9d..a1335d3 100644 --- a/interface/popup/cookie-list.js +++ b/interface/popup/cookie-list.js @@ -1064,6 +1064,7 @@ import { CookieHandlerPopup } from './cookieHandlerPopup.js'; async function initWindow(_tab) { await optionHandler.loadOptions(); themeHandler.updateTheme(); + moveButtonBar(); handleAd(); handleAnimationsEnabled(); optionHandler.on('optionsChanged', onOptionsChanged); @@ -1331,6 +1332,7 @@ import { CookieHandlerPopup } from './cookieHandlerPopup.js'; */ function onOptionsChanged(oldOptions) { handleAnimationsEnabled(); + moveButtonBar(); if (oldOptions.advancedCookies != optionHandler.getCookieAdvanced()) { document.querySelector('#advanced-toggle-all').checked = optionHandler.getCookieAdvanced(); @@ -1341,4 +1343,21 @@ import { CookieHandlerPopup } from './cookieHandlerPopup.js'; showCookiesForTab(); } } + + /** + * Moves the button bar to the top or bottom depending on the user preference + */ + function moveButtonBar() { + const siblingElement = optionHandler.getButtonBarTop() + ? document.getElementById('pageTitle').nextSibling + : document.body.lastChild; + document.querySelectorAll('.button-bar').forEach((bar) => { + siblingElement.parentNode.insertBefore(bar, siblingElement); + if (optionHandler.getButtonBarTop()) { + document.body.classList.add('button-bar-top'); + } else { + document.body.classList.remove('button-bar-top'); + } + }); + } })(); diff --git a/interface/popup/style.css b/interface/popup/style.css index 636c038..f82e02c 100644 --- a/interface/popup/style.css +++ b/interface/popup/style.css @@ -468,11 +468,6 @@ label { margin: 0; } -.panel-section-footer-button { - font-size: 14px; - line-height: 14px; -} - .button-bar { display: none; z-index: 5; @@ -567,7 +562,15 @@ body, user-select: none; overflow: hidden; } + +.button-bar-top .panel-section-footer { + border-top: none; + border-bottom: 1px solid rgba(0, 0, 0, 0.15); +} + .panel-section-footer-button { + font-size: 14px; + line-height: 14px; flex: 1 1; padding: 12px; text-align: center; @@ -643,6 +646,10 @@ body, padding: 0 25px; } +.button-bar-top #notification-container { + bottom: 15px; +} + #notification { position: relative; display: inline-block; @@ -853,6 +860,17 @@ body, border-right: solid 10px transparent; } +.button-bar-top #export-menu { + top: 92px; + bottom: auto; +} +.button-bar-top #export-menu:after { + top: auto; + bottom: 100%; + border-top: none; + border-bottom: solid 10px var(--menu-surface-color); +} + #export-menu h3 { margin-top: 0; margin-left: 2px;