feat: improve section data backend

Signed-off-by: JustAdumbPrsn <73780892+JustAdumbPrsn@users.noreply.github.com>
This commit is contained in:
JustAdumbPrsn
2026-03-09 20:38:20 +05:30
committed by GitHub
parent 556beb01b0
commit 88ebf6e5da

View File

@@ -7,32 +7,38 @@ import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
let lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
Downloads: "resource://gre/modules/Downloads.sys.mjs",
DownloadHistory: "resource://gre/modules/DownloadHistory.sys.mjs",
DownloadUtils: "resource://gre/modules/DownloadUtils.sys.mjs",
PlacesQuery: "resource://gre/modules/PlacesQuery.sys.mjs",
});
ChromeUtils.defineLazyGetter(lazy, "l10n", function () {
return new Localization(
["browser/zen-library.ftl"],
true
);
return new Localization(["browser/zen-library.ftl"], true);
});
class LibrarySection extends MozLitElement {
static largeContent = false;
static get id() {
throw new Error("Unimplemented");
throw new Error("LibrarySection subclass must define a static `id`.");
}
static get label() {
throw new Error("Unimplemented");
throw new Error("LibrarySection subclass must define a static `label`.");
}
}
class SearchSection extends LibrarySection {
static properties = {
searchTerm: { type: String },
isEmpty: { type: Boolean },
};
connectedCallback() {
this.searchTerm = "";
this.isEmpty = false;
super.connectedCallback();
}
@@ -42,12 +48,15 @@ class SearchSection extends LibrarySection {
}
renderSearchResults() {
return html`${this.searchTerm}`;
return html``;
}
render() {
return html`
<link rel="stylesheet" href="chrome://browser/content/zen-styles/zen-library.css" />
<link
rel="stylesheet"
href="chrome://browser/content/zen-styles/zen-library.css"
/>
<hbox class="search-section">
<image src="chrome://browser/skin/zen-icons/search-glass.svg" />
<input
@@ -58,30 +67,136 @@ class SearchSection extends LibrarySection {
.value=${this.searchTerm}
/>
</hbox>
<div class="search-results">
${this.renderSearchResults()}
</div>
<div class="search-results">${this.renderSearchResults()}</div>
`;
}
}
// History section
class ZenLibraryHistorySection extends SearchSection {
static id = "history";
static label = "library-history-section-title";
#placesQuery = null;
#history = null;
renderSearchResults() {
if (this.isEmpty) {
return html`<div class="empty-state">
${lazy.l10n.formatValueSync("library-history-empty")}
</div>`;
}
return html`${this.searchTerm}`;
}
async connectedCallback() {
super.connectedCallback();
try {
this.#placesQuery = new lazy.PlacesQuery();
this.#history = await this.#placesQuery.getHistory();
this.isEmpty = this.#history.size === 0;
this.#placesQuery.observeHistory((newHistory) => {
this.#history = newHistory;
this.isEmpty = this.#history.size === 0;
this.requestUpdate();
});
this.requestUpdate();
} catch (ex) {
console.error("Zen Library: Failed to initialize history section.", ex);
}
}
disconnectedCallback() {
super.disconnectedCallback();
this.#placesQuery?.close();
this.#placesQuery = null;
this.#history = null;
}
}
// Downloads section
class ZenLibraryDownloadsSection extends SearchSection {
static id = "downloads";
static label = "library-downloads-section-title";
#downloadList = null;
#downloads = [];
#downloadsView = null;
#batchLoading = false;
renderSearchResults() {
if (this.isEmpty) {
return html`<div class="empty-state">
${lazy.l10n.formatValueSync("library-downloads-empty")}
</div>`;
}
return html`${this.searchTerm}`;
}
async connectedCallback() {
super.connectedCallback();
try {
this.#downloadList = await lazy.DownloadHistory.getList({
type: lazy.Downloads.PUBLIC,
});
this.#downloadsView = {
onDownloadAdded: (dl) => {
// During the initial batch replay addView fires onDownloadAdded for
// every existing download oldest-first, so we push to preserve order.
// After init, new downloads are unshifted to the front.
if (this.#batchLoading) {
this.#downloads.push(dl);
} else {
this.#downloads.unshift(dl);
this.isEmpty = false;
this.requestUpdate();
}
},
onDownloadBatchEnded: () => {
this.#batchLoading = false;
this.isEmpty = this.#downloads.length === 0;
this.requestUpdate();
},
onDownloadChanged: (dl) => {
this.requestUpdate();
},
onDownloadRemoved: (dl) => {
this.#downloads = this.#downloads.filter((d) => d !== dl);
this.isEmpty = this.#downloads.length === 0;
this.requestUpdate();
},
};
this.#batchLoading = true;
this.#downloadList.addView(this.#downloadsView);
} catch (ex) {
console.error("Zen Library: Failed to initialize downloads section.", ex);
}
}
disconnectedCallback() {
super.disconnectedCallback();
if (this.#downloadList && this.#downloadsView) {
this.#downloadList.removeView(this.#downloadsView);
}
this.#downloadList = null;
this.#downloadsView = null;
this.#downloads = [];
}
}
// Spaces section
class ZenLibrarySpacesSection extends LibrarySection {
static largeContent = true;
static id = "spaces";
static label = "library-spaces-section-title";
}
export const ZenLibrarySections = {
history: class extends SearchSection {
static id = "history";
static label = "library-history-section-title";
},
downloads: class extends SearchSection {
static id = "downloads";
static label = "library-downloads-section-title";
},
spaces: class extends LibrarySection {
static largeContent = true;
static id = "spaces";
static label = "library-spaces-section-title";
},
history: ZenLibraryHistorySection,
downloads: ZenLibraryDownloadsSection,
spaces: ZenLibrarySpacesSection,
};
for (const section of Object.values(ZenLibrarySections)) {
customElements.define(`zen-library-section-${section.id}`, section)
;
for (const Section of Object.values(ZenLibrarySections)) {
customElements.define(`zen-library-section-${Section.id}`, Section);
}