refactor: Update ZenThemeMarketplaceParent to download and install themes

This commit updates the ZenThemeMarketplaceParent module to include the functionality for downloading and installing themes. The `receiveMessage` method now handles the "ZenThemeMarketplace:InstallTheme" message by downloading the theme file contents and updating the themes data. The `downloadUrlToFile` method has been added to download the file from the provided URL and save it to the specified path. Additionally, the `downloadThemeFileContents` method has been added to download the style and readme files for a theme and save them to the appropriate directory.

Refactor ZenThemeMarketplaceParent.sys.mjs:
- Add `downloadUrlToFile` method
- Add `downloadThemeFileContents` method
This commit is contained in:
Mauro Balades 2024-08-16 22:10:54 +02:00
parent 2e098ebf17
commit 1f01cdac79

View file

@ -1,55 +1,58 @@
const kZenThemesPreference = "zen.themes.data";
export class ZenThemeMarketplaceParent extends JSWindowActorParent { export class ZenThemeMarketplaceParent extends JSWindowActorParent {
constructor() { constructor() {
super(); super();
Services.prefs.addObserver(kZenThemesPreference, this.onThemePreferenceChange.bind(this));
} }
receiveMessage(message) { async receiveMessage(message) {
switch (message.name) { switch (message.name) {
case "ZenThemeMarketplace:UpdateThemes": { case "ZenThemeMarketplace:InstallTheme": {
console.info("ZenThemeMarketplaceParent: Updating themes"); console.info("ZenThemeMarketplaceParent: Updating themes");
this.updateThemes(message.data.themes); const theme = message.data.theme;
const themes = await this.getThemes();
themes[theme.id] = theme;
this.updateThemes(themes);
break; break;
} }
} }
} }
get themes() { async getThemes() {
if (!this._themes) { if (!this._themes) {
this._themes = JSON.parse(Services.prefs.getStringPref(kZenThemesPreference, "{}")); if (!(await IOUtils.exists(this.themesDataFile))) {
await IOUtils.writeJSON(this.themesDataFile, {});
}
this._themes = await IOUtils.readJSON(this.themesDataFile);
} }
return this._themes; return this._themes;
} }
updateThemes(themes) { updateThemes(themes) {
Services.prefs.setStringPref(kZenThemesPreference, JSON.stringify(themes)); this._themes = themes;
} IOUtils.writeJSON(this.themesDataFile, themes);
onThemePreferenceChange() {
this._themes = null;
this.checkForThemeChanges(); this.checkForThemeChanges();
} }
async getDownloadFileContents(themeId) { async downloadUrlToFile(url, path) {
try { try {
const theme = this.themes[themeId]; console.info("ZenThemeMarketplaceParent: Downloading file from ", url);
if (!theme) { const response = await fetch(url);
throw new Error("Theme not found");
}
const downloadUrl = theme.downloadUrl;
console.info("ZenThemeMarketplaceParent: Downloading file from ", downloadUrl);
const response = await fetch(downloadUrl);
const data = await response.text(); const data = await response.text();
return data; // convert the data into a Uint8Array
let buffer = new TextEncoder().encode(data);
await IOUtils.write(path, buffer);
} catch (e) { } catch (e) {
console.error("ZenThemeMarketplaceParent: Error getting downloadable file", e); console.error("ZenThemeMarketplaceParent: Error downloading file", e);
return "";
} }
} }
async downloadThemeFileContents(theme) {
const themePath = PathUtils.join(this.themesRootPath, theme.id);
await IOUtils.makeDirectory(themePath, { ignoreExisting: true });
await this.downloadUrlToFile(theme.style, PathUtils.join(themePath, "chrome.css"));
await this.downloadUrlToFile(theme.readme, PathUtils.join(themePath, "readme.md"));
}
get themesRootPath() { get themesRootPath() {
return PathUtils.join( return PathUtils.join(
PathUtils.profileDir, PathUtils.profileDir,
@ -58,10 +61,31 @@ export class ZenThemeMarketplaceParent extends JSWindowActorParent {
); );
} }
// Compare the downloaded themes to the "installed" themes get themesDataFile() {
// and update the installed themes with the new ones. We may also return PathUtils.join(
// delete any themes that are no longer available. PathUtils.profileDir,
async checkForThemeChanges() { "zen-themes.json"
);
}
async installTheme(theme) {
await this.downloadThemeFileContents(theme);
this.sendAsyncMessage("ZenThemeMarketplace:ThemeInstalled", { theme });
}
async checkForThemeChanges() {
const themes = await this.getThemes();
const themeIds = Object.keys(themes);
for (const themeId of themeIds) {
const theme = themes[themeId];
if (!theme) {
continue;
}
const themePath = PathUtils.join(this.themesRootPath, themeId);
if (!(await IOUtils.exists(themePath))) {
console.info("ZenThemeMarketplaceParent: Installing theme ", themeId);
this.installTheme(theme);
}
}
} }
}; };