diff --git a/src/browser/base/content/zen-assets.inc.xhtml b/src/browser/base/content/zen-assets.inc.xhtml index 88e141bc5..addf290d8 100644 --- a/src/browser/base/content/zen-assets.inc.xhtml +++ b/src/browser/base/content/zen-assets.inc.xhtml @@ -26,6 +26,7 @@ \ No newline at end of file + diff --git a/src/browser/components/preferences/zen-settings.js b/src/browser/components/preferences/zen-settings.js index aced28e2c..8a7f4d41c 100644 --- a/src/browser/components/preferences/zen-settings.js +++ b/src/browser/components/preferences/zen-settings.js @@ -2,25 +2,6 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -const kZenColors = [ - '#aac7ff', - '#74d7cb', - '#a0d490', - '#dec663', - '#ffb787', - '#dec1b1', - '#ffb1c0', - '#ddbfc3', - '#f6b0ea', - '#d4bbff', -]; - -const kZenOSToSmallName = { - WINNT: 'windows', - Darwin: 'macos', - Linux: 'linux', -}; - var gZenMarketplaceManager = { init() { const checkForUpdates = document.getElementById('zenThemeMarketplaceCheckForUpdates'); @@ -79,138 +60,42 @@ var gZenMarketplaceManager = { return document.getElementById('zenThemeMarketplaceList'); }, - get themesDataFile() { - return PathUtils.join(PathUtils.profileDir, 'zen-themes.json'); - }, - - get themesRootPath() { - return PathUtils.join(PathUtils.profileDir, 'chrome', 'zen-themes'); - }, - async removeTheme(themeId) { - const themePath = PathUtils.join(this.themesRootPath, themeId); - console.info('ZenThemeMarketplaceParent(settings): Removing theme ', themePath); + const themePath = ZenThemesCommon.getThemeFolder(themeId); + + console.info(`[ZenThemeMarketplaceParent:settings]: Removing theme ${themePath}`); + await IOUtils.remove(themePath, { recursive: true, ignoreAbsent: true }); - let themes = await this._getThemes(); + const themes = await ZenThemesCommon.getThemes(); delete themes[themeId]; - await IOUtils.writeJSON(this.themesDataFile, themes); + await IOUtils.writeJSON(ZenThemesCommon.themesDataFile, themes); this.triggerThemeUpdate(); }, async disableTheme(themeId) { - const themes = await this._getThemes(); + const themes = await ZenThemesCommon.getThemes(); const theme = themes[themeId]; theme.enabled = false; - await IOUtils.writeJSON(this.themesDataFile, themes); + await IOUtils.writeJSON(ZenThemesCommon.themesDataFile, themes); this._doNotRebuildThemesList = true; this.triggerThemeUpdate(); }, async enableTheme(themeId) { - const themes = await this._getThemes(); + const themes = await ZenThemesCommon.getThemes(); const theme = themes[themeId]; theme.enabled = true; - await IOUtils.writeJSON(this.themesDataFile, themes); + await IOUtils.writeJSON(ZenThemesCommon.themesDataFile, themes); this._doNotRebuildThemesList = true; this.triggerThemeUpdate(); }, - async _getThemes() { - if (!this._themes) { - if (!(await IOUtils.exists(this.themesDataFile))) { - await IOUtils.writeJSON(this.themesDataFile, {}); - } - this._themes = await IOUtils.readJSON(this.themesDataFile); - } - return this._themes; - }, - - get currentOperatingSystem() { - let os = Services.appinfo.OS; - return kZenOSToSmallName[os]; - }, - - _getValidPreferences(preferences) { - for (let entry of preferences) { - const key = entry.property; - // [!][os:]key - let restOfPreferences = key; - let isNegation = false; - if (key.startsWith('!')) { - isNegation = true; - restOfPreferences = key.slice(1); - } - let os = ''; - if (restOfPreferences.includes(':')) { - [os, restOfPreferences] = restOfPreferences.split(':'); - } - if (isNegation && os === this.currentOperatingSystem) { - delete preferences[key]; - } else if (os && os !== this.currentOperatingSystem && !isNegation) { - delete preferences[key]; - } else { - // Change the key to contain only the rest of the preferences. - preferences[restOfPreferences] = preferences[key]; - if (key !== restOfPreferences) { - delete preferences[key]; - } - } - } - return preferences; - }, - - async _getThemePreferences(theme) { - const themePath = PathUtils.join(this.themesRootPath, theme.id, 'preferences.json'); - if (!(await IOUtils.exists(themePath)) || !theme.preferences) { - return []; - } - - let themePreferences = await IOUtils.readJSON(themePath); - - // compat mode for old preferences, all of them can only be checkboxes - if (typeof themePreferences === 'object' && !Array.isArray(themePreferences)) { - console.warn( - `[ZenThemeMarketplaceManager]: Warning, ${theme.name} uses legacy preferences, please migrate them to the new preferences style, as legacy preferences might be removed at a future release. More information at: ` - ); - themePreferences = Object.entries(themePreferences).map(([property, label]) => { - return { - property, - label, - type: 'checkbox', - }; - }); - } - - return this._getValidPreferences(themePreferences); - }, - - _getBrowser() { - if (!this.__browser) { - this.__browser = Services.wm.getMostRecentWindow('navigator:browser'); - } - - return this.__browser; - }, - - __throttle(mainFunction, delay) { - let timerFlag = null; - - return (...args) => { - if (timerFlag === null) { - mainFunction(...args); - timerFlag = setTimeout(() => { - timerFlag = null; - }, delay); - } - }; - }, - async _buildThemesList() { if (!this.themesList) return; if (this._doNotRebuildThemesList) { @@ -218,16 +103,17 @@ var gZenMarketplaceManager = { return; } - console.log('ZenThemeMarketplaceParent(settings): Building themes list'); + console.log('[ZenThemeMarketplaceParent:settings]: Building themes list'); - let themes = await this._getThemes(); + let themes = await ZenThemesCommon.getThemes(); - const browser = this._getBrowser(); + const browser = ZenThemesCommon.getBrowser(); const themeList = document.createElement('div'); - for (let theme of Object.values(themes)) { + for (const theme of Object.values(themes)) { const sanitizedName = `theme-${theme.name?.replaceAll(/\s/g, '-')?.replaceAll(/[^A-z_-]+/g, '')}`; + const isThemeEnabled = theme.enabled === undefined || theme.enabled; const fragment = window.MozXULElement.parseXULToFragment(` @@ -238,7 +124,7 @@ var gZenMarketplaceManager = { - + ${theme.preferences ? `` : ''} @@ -260,16 +146,21 @@ var gZenMarketplaceManager = { mainDialogDiv.className = 'zenThemeMarketplaceItemPreferenceDialog'; headerDiv.className = 'zenThemeMarketplaceItemPreferenceDialogTopBar'; headerTitle.textContent = themeName; - headerTitle.title = `CSS Selector: ${sanitizedName}`; + browser.document.l10n.setAttributes(headerTitle, 'zen-theme-marketplace-theme-header-title', { + name: sanitizedName, + }); headerTitle.className = 'zenThemeMarketplaceItemTitle'; closeButton.id = `${sanitizedName}-modal-close`; - closeButton.textContent = 'Close'; + browser.document.l10n.setAttributes(closeButton, 'zen-theme-marketplace-close-modal'); contentDiv.id = `${sanitizedName}-preferences-content`; contentDiv.className = 'zenThemeMarketplaceItemPreferenceDialogContent'; mozToggle.className = 'zenThemeMarketplaceItemPreferenceToggle'; - mozToggle.pressed = theme.enabled; - mozToggle.title = theme.enabled ? 'Disable theme' : 'Enable theme'; + mozToggle.pressed = isThemeEnabled; + browser.document.l10n.setAttributes( + mozToggle, + `zen-theme-marketplace-toggle-${isThemeEnabled ? 'enabled' : 'disabled'}-button` + ); baseHeader.appendChild(mozToggle); @@ -293,39 +184,53 @@ var gZenMarketplaceManager = { if (!event.target.hasAttribute('pressed')) { await this.disableTheme(themeId); - document.getElementById(`zenThemeMarketplaceItemConfigureButton-${sanitizedName}`).setAttribute('hidden', true); + + browser.document.l10n.setAttributes(mozToggle, 'zen-theme-marketplace-toggle-disabled-button'); + + if (theme.preferences) { + document.getElementById(`zenThemeMarketplaceItemConfigureButton-${sanitizedName}`).setAttribute('hidden', true); + } } else { await this.enableTheme(themeId); - document.getElementById(`zenThemeMarketplaceItemConfigureButton-${sanitizedName}`).removeAttribute('hidden'); + + browser.document.l10n.setAttributes(mozToggle, 'zen-theme-marketplace-toggle-enabled-button'); + + if (theme.preferences) { + document.getElementById(`zenThemeMarketplaceItemConfigureButton-${sanitizedName}`).removeAttribute('hidden'); + } } }); fragment.querySelector('.zenThemeMarketplaceItemTitle').textContent = themeName; fragment.querySelector('.zenThemeMarketplaceItemDescription').textContent = theme.description; fragment.querySelector('.zenThemeMarketplaceItemUninstallButton').addEventListener('click', async (event) => { - if (!confirm('Are you sure you want to remove this theme?')) { + const [msg] = await document.l10n.formatValues([{ id: 'zen-theme-marketplace-remove-confirmation' }]); + + if (!confirm(msg)) { return; } - const target = event.target; - const themeId = target.getAttribute('zen-theme-id'); - await this.removeTheme(themeId); - }); - fragment.querySelector('.zenThemeMarketplaceItemConfigureButton').addEventListener('click', () => { - dialog.showModal(); + + await this.removeTheme(event.target.getAttribute('zen-theme-id')); }); - if (theme.enabled && theme.preferences) { - fragment.querySelector('.zenThemeMarketplaceItemConfigureButton').removeAttribute('hidden'); + if (theme.preferences) { + fragment.querySelector('.zenThemeMarketplaceItemConfigureButton').addEventListener('click', () => { + dialog.showModal(); + }); + + if (isThemeEnabled) { + fragment.querySelector('.zenThemeMarketplaceItemConfigureButton').removeAttribute('hidden'); + } } - const preferences = await this._getThemePreferences(theme); + const preferences = await ZenThemesCommon.getThemePreferences(theme); if (preferences.length > 0) { const preferencesWrapper = document.createXULElement('vbox'); preferencesWrapper.setAttribute('flex', '1'); - for (let entry of preferences) { + for (const entry of preferences) { const { property, label, type } = entry; switch (type) { @@ -355,14 +260,14 @@ var gZenMarketplaceManager = { menupopup.appendChild(defaultItem); - for (let option of options) { + for (const option of options) { const { label, value } = option; const valueType = typeof value; if (!['string', 'number'].includes(valueType)) { console.log( - `ZenThemeMarketplaceParent(settings): Warning, invalid data type received (${valueType}), skipping.` + `[ZenThemeMarketplaceParent:settings]: Warning, invalid data type received (${valueType}), skipping.` ); continue; } @@ -423,9 +328,9 @@ var gZenMarketplaceManager = { } checkbox.querySelector('.zenThemeMarketplaceItemPreferenceCheckbox').addEventListener('click', (event) => { - let target = event.target.closest('.zenThemeMarketplaceItemPreferenceCheckbox'); - let key = target.getAttribute('zen-pref'); - let checked = target.hasAttribute('checked'); + const target = event.target.closest('.zenThemeMarketplaceItemPreferenceCheckbox'); + const key = target.getAttribute('zen-pref'); + const checked = target.hasAttribute('checked'); if (!checked) { target.removeAttribute('checked'); @@ -457,7 +362,7 @@ var gZenMarketplaceManager = { input.addEventListener( 'input', - this.__throttle((event) => { + ZenThemesCommon.throttle((event) => { const value = event.target.value; Services.prefs.setStringPref(property, value); @@ -486,7 +391,7 @@ var gZenMarketplaceManager = { default: console.log( - `ZenThemeMarketplaceParent(settings): Warning, unknown preference type received (${type}), skipping.` + `[ZenThemeMarketplaceParent:settings]: Warning, unknown preference type received (${type}), skipping.` ); continue; } @@ -608,7 +513,7 @@ var gZenLooksAndFeel = { _initializeColorPicker(accentColor) { let elem = document.getElementById('zenLooksAndFeelColorOptions'); elem.innerHTML = ''; - for (let color of kZenColors) { + for (let color of ZenThemesCommon.kZenColors) { let colorElemParen = document.createElement('div'); let colorElem = document.createElement('div'); colorElemParen.classList.add('zenLooksAndFeelColorOptionParen'); @@ -631,7 +536,7 @@ var gZenLooksAndFeel = { }, _getInitialAccentColor() { - return Services.prefs.getStringPref('zen.theme.accent-color', kZenColors[0]); + return Services.prefs.getStringPref('zen.theme.accent-color', ZenThemesCommon.kZenColors[0]); }, }; diff --git a/src/browser/themes/shared/preferences/zen-preferences.css b/src/browser/themes/shared/preferences/zen-preferences.css index ad37698d0..ba7614262 100644 --- a/src/browser/themes/shared/preferences/zen-preferences.css +++ b/src/browser/themes/shared/preferences/zen-preferences.css @@ -480,6 +480,10 @@ groupbox h2 { flex-direction: row; } +.zenThemeMarketplaceItemPreferenceToggle { + align-self: start; +} + #zenThemeMarketplaceItemContentHeader { display: flex; flex-direction: row;