mirror of
https://github.com/zen-browser/desktop.git
synced 2025-10-05 17:36:34 +00:00
Add theme import and export functionality
Implemented theme import and export options in the Zen Theme Marketplace. Added buttons, event handlers, and logic for users to save themes to a file or load them from an external JSON file. Included success and error states for both actions.
This commit is contained in:
@@ -16,6 +16,8 @@ var gZenMarketplaceManager = {
|
|||||||
|
|
||||||
header.appendChild(this._initDisableAll());
|
header.appendChild(this._initDisableAll());
|
||||||
|
|
||||||
|
this._initImportExport();
|
||||||
|
|
||||||
this.__hasInitializedEvents = true;
|
this.__hasInitializedEvents = true;
|
||||||
|
|
||||||
await this._buildThemesList();
|
await this._buildThemesList();
|
||||||
@@ -56,6 +58,23 @@ var gZenMarketplaceManager = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_initImportExport() {
|
||||||
|
const importButton = document.getElementById('zenThemeMarketplaceImport');
|
||||||
|
const exportButton = document.getElementById('zenThemeMarketplaceExport');
|
||||||
|
|
||||||
|
if (importButton) {
|
||||||
|
importButton.addEventListener('click', async () => {
|
||||||
|
await this._importThemes();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exportButton) {
|
||||||
|
exportButton.addEventListener('click', async () => {
|
||||||
|
await this._exportThemes();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
_initDisableAll() {
|
_initDisableAll() {
|
||||||
const areThemesDisabled = Services.prefs.getBoolPref('zen.themes.disable-all', false);
|
const areThemesDisabled = Services.prefs.getBoolPref('zen.themes.disable-all', false);
|
||||||
const browser = ZenThemesCommon.currentBrowser;
|
const browser = ZenThemesCommon.currentBrowser;
|
||||||
@@ -153,6 +172,89 @@ var gZenMarketplaceManager = {
|
|||||||
this.triggerThemeUpdate();
|
this.triggerThemeUpdate();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async _importThemes() {
|
||||||
|
const errorBox = document.getElementById('zenThemeMarketplaceImportFailure');
|
||||||
|
const successBox = document.getElementById('zenThemeMarketplaceImportSuccess');
|
||||||
|
successBox.hidden = true;
|
||||||
|
errorBox.hidden = true;
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'file';
|
||||||
|
input.accept = '.json';
|
||||||
|
input.style.display = 'none';
|
||||||
|
input.setAttribute('moz-accept', '.json');
|
||||||
|
input.setAttribute('accept', '.json');
|
||||||
|
|
||||||
|
let timeout;
|
||||||
|
const filePromise = new Promise((resolve) => {
|
||||||
|
input.addEventListener('change', (event) => {
|
||||||
|
if (timeout) clearTimeout(timeout);
|
||||||
|
const file = event.target.files[0];
|
||||||
|
resolve(file);
|
||||||
|
});
|
||||||
|
timeout = setTimeout(() => {
|
||||||
|
console.warn('[ZenThemeMarketplaceParent:settings]: Import timeout reached, aborting.');
|
||||||
|
resolve(null);
|
||||||
|
}, 60000);
|
||||||
|
});
|
||||||
|
|
||||||
|
input.click();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const file = await filePromise;
|
||||||
|
if (!file) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const content = await file.text();
|
||||||
|
|
||||||
|
const themes = JSON.parse(content);
|
||||||
|
const existingThemes = await ZenThemesCommon.getThemes();
|
||||||
|
const uniqueThemes = { ...themes, ...existingThemes };
|
||||||
|
|
||||||
|
console.log(`[ZenThemeMarketplaceParent:settings]: Importing ${Object.keys(themes).length} themes`);
|
||||||
|
await IOUtils.writeJSON(ZenThemesCommon.themesDataFile, uniqueThemes);
|
||||||
|
this.triggerThemeUpdate();
|
||||||
|
successBox.hidden = false;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[ZenThemeMarketplaceParent:settings]: Error while importing themes:', error);
|
||||||
|
errorBox.hidden = false;
|
||||||
|
} finally {
|
||||||
|
if (input) input.remove();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async _exportThemes() {
|
||||||
|
const errorBox = document.getElementById('zenThemeMarketplaceExportFailure');
|
||||||
|
const successBox = document.getElementById('zenThemeMarketplaceExportSuccess');
|
||||||
|
|
||||||
|
successBox.hidden = true;
|
||||||
|
errorBox.hidden = true;
|
||||||
|
|
||||||
|
let a, url;
|
||||||
|
try {
|
||||||
|
const themes = await ZenThemesCommon.getThemes();
|
||||||
|
const themesJson = JSON.stringify(themes, null, 2);
|
||||||
|
const blob = new Blob([themesJson], { type: 'application/json' });
|
||||||
|
url = URL.createObjectURL(blob);
|
||||||
|
// Creating a link to download the JSON file
|
||||||
|
a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = 'zen-themes-export.json';
|
||||||
|
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[ZenThemeMarketplaceParent:settings]: Error while exporting themes:', error);
|
||||||
|
errorBox.hidden = false;
|
||||||
|
} finally {
|
||||||
|
if (a) {
|
||||||
|
a.remove();
|
||||||
|
}
|
||||||
|
if (url) {
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
async _buildThemesList() {
|
async _buildThemesList() {
|
||||||
if (!this.themesList) {
|
if (!this.themesList) {
|
||||||
return;
|
return;
|
||||||
|
@@ -16,12 +16,20 @@
|
|||||||
<description class="description-deemphasized" data-l10n-id="zen-theme-marketplace-description" />
|
<description class="description-deemphasized" data-l10n-id="zen-theme-marketplace-description" />
|
||||||
<hbox class="indent">
|
<hbox class="indent">
|
||||||
<html:a id="zenThemeMarketplaceLink" href="https://zen-browser.app/mods/" target="_blank" data-l10n-id="zen-theme-marketplace-link" />
|
<html:a id="zenThemeMarketplaceLink" href="https://zen-browser.app/mods/" target="_blank" data-l10n-id="zen-theme-marketplace-link" />
|
||||||
|
<button id="zenThemeMarketplaceImport" data-l10n-id="zen-theme-marketplace-import-button" />
|
||||||
|
<button id="zenThemeMarketplaceExport" data-l10n-id="zen-theme-marketplace-export-button" />
|
||||||
<button id="zenThemeMarketplaceCheckForUpdates" data-l10n-id="zen-theme-marketplace-check-for-updates-button" />
|
<button id="zenThemeMarketplaceCheckForUpdates" data-l10n-id="zen-theme-marketplace-check-for-updates-button" />
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
||||||
<description class="description-deemphasized" data-l10n-id="zen-theme-marketplace-updates-success" hidden="true" id="zenThemeMarketplaceUpdatesSuccess" />
|
<description class="description-deemphasized" data-l10n-id="zen-theme-marketplace-updates-success" hidden="true" id="zenThemeMarketplaceUpdatesSuccess" />
|
||||||
<description class="description-deemphasized" data-l10n-id="zen-theme-marketplace-updates-failure" hidden="true" id="zenThemeMarketplaceUpdatesFailure" />
|
<description class="description-deemphasized" data-l10n-id="zen-theme-marketplace-updates-failure" hidden="true" id="zenThemeMarketplaceUpdatesFailure" />
|
||||||
|
|
||||||
|
<description class="description-deemphasized" data-l10n-id="zen-theme-marketplace-import-success" hidden="true" id="zenThemeMarketplaceImportSuccess" />
|
||||||
|
<description class="description-deemphasized" data-l10n-id="zen-theme-marketplace-import-failure" hidden="true" id="zenThemeMarketplaceImportFailure" />
|
||||||
|
|
||||||
|
<description class="description-deemphasized" data-l10n-id="zen-theme-marketplace-export-success" hidden="true" id="zenThemeMarketplaceExportSuccess" />
|
||||||
|
<description class="description-deemphasized" data-l10n-id="zen-theme-marketplace-export-failure" hidden="true" id="zenThemeMarketplaceExportFailure" />
|
||||||
|
|
||||||
<vbox id="zenThemeMarketplaceList"></vbox>
|
<vbox id="zenThemeMarketplaceList"></vbox>
|
||||||
</groupbox>
|
</groupbox>
|
||||||
|
|
||||||
|
@@ -560,12 +560,23 @@ groupbox h2 {
|
|||||||
|
|
||||||
.zenThemeMarketplaceItemUninstallButton {
|
.zenThemeMarketplaceItemUninstallButton {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#zenThemeMarketplaceImport {
|
||||||
|
margin-left: auto;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#zenThemeMarketplaceExport {
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
#zenThemeMarketplaceCheckForUpdates {
|
#zenThemeMarketplaceCheckForUpdates {
|
||||||
margin-left: auto;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.zenThemeMarketplaceItemPreferenceDialog {
|
.zenThemeMarketplaceItemPreferenceDialog {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
Reference in New Issue
Block a user