summaryrefslogtreecommitdiffstats
path: root/browser/components/firefoxview/firefox-view-places-query.sys.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/firefoxview/firefox-view-places-query.sys.mjs')
-rw-r--r--browser/components/firefoxview/firefox-view-places-query.sys.mjs187
1 files changed, 187 insertions, 0 deletions
diff --git a/browser/components/firefoxview/firefox-view-places-query.sys.mjs b/browser/components/firefoxview/firefox-view-places-query.sys.mjs
new file mode 100644
index 0000000000..8923905769
--- /dev/null
+++ b/browser/components/firefoxview/firefox-view-places-query.sys.mjs
@@ -0,0 +1,187 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+import { PlacesQuery } from "resource://gre/modules/PlacesQuery.sys.mjs";
+
+/**
+ * Extension of PlacesQuery which provides additional caches for Firefox View.
+ */
+export class FirefoxViewPlacesQuery extends PlacesQuery {
+ /** @type {Date} */
+ #todaysDate = null;
+ /** @type {Date} */
+ #yesterdaysDate = null;
+
+ get visitsFromToday() {
+ if (this.cachedHistory == null || this.#todaysDate == null) {
+ return [];
+ }
+ const mapKey = this.getStartOfDayTimestamp(this.#todaysDate);
+ return this.cachedHistory.get(mapKey) ?? [];
+ }
+
+ get visitsFromYesterday() {
+ if (this.cachedHistory == null || this.#yesterdaysDate == null) {
+ return [];
+ }
+ const mapKey = this.getStartOfDayTimestamp(this.#yesterdaysDate);
+ return this.cachedHistory.get(mapKey) ?? [];
+ }
+
+ /**
+ * Get a list of visits per day for each day on this month, excluding today
+ * and yesterday.
+ *
+ * @returns {HistoryVisit[][]}
+ * A list of visits for each day.
+ */
+ get visitsByDay() {
+ const visitsPerDay = [];
+ for (const [time, visits] of this.cachedHistory.entries()) {
+ const date = new Date(time);
+ if (
+ this.#isSameDate(date, this.#todaysDate) ||
+ this.#isSameDate(date, this.#yesterdaysDate)
+ ) {
+ continue;
+ } else if (!this.#isSameMonth(date, this.#todaysDate)) {
+ break;
+ } else {
+ visitsPerDay.push(visits);
+ }
+ }
+ return visitsPerDay;
+ }
+
+ /**
+ * Get a list of visits per month for each month, excluding this one, and
+ * excluding yesterday's visits if yesterday happens to fall on the previous
+ * month.
+ *
+ * @returns {HistoryVisit[][]}
+ * A list of visits for each month.
+ */
+ get visitsByMonth() {
+ const visitsPerMonth = [];
+ let previousMonth = null;
+ for (const [time, visits] of this.cachedHistory.entries()) {
+ const date = new Date(time);
+ if (
+ this.#isSameMonth(date, this.#todaysDate) ||
+ this.#isSameDate(date, this.#yesterdaysDate)
+ ) {
+ continue;
+ }
+ const month = this.getStartOfMonthTimestamp(date);
+ if (month !== previousMonth) {
+ visitsPerMonth.push(visits);
+ } else {
+ visitsPerMonth[visitsPerMonth.length - 1] = visitsPerMonth
+ .at(-1)
+ .concat(visits);
+ }
+ previousMonth = month;
+ }
+ return visitsPerMonth;
+ }
+
+ formatRowAsVisit(row) {
+ const visit = super.formatRowAsVisit(row);
+ this.#normalizeVisit(visit);
+ return visit;
+ }
+
+ formatEventAsVisit(event) {
+ const visit = super.formatEventAsVisit(event);
+ this.#normalizeVisit(visit);
+ return visit;
+ }
+
+ /**
+ * Normalize data for fxview-tabs-list.
+ *
+ * @param {HistoryVisit} visit
+ * The visit to format.
+ */
+ #normalizeVisit(visit) {
+ visit.time = visit.date.getTime();
+ visit.title = visit.title || visit.url;
+ visit.icon = `page-icon:${visit.url}`;
+ visit.primaryL10nId = "fxviewtabrow-tabs-list-tab";
+ visit.primaryL10nArgs = JSON.stringify({
+ targetURI: visit.url,
+ });
+ visit.secondaryL10nId = "fxviewtabrow-options-menu-button";
+ visit.secondaryL10nArgs = JSON.stringify({
+ tabTitle: visit.title || visit.url,
+ });
+ }
+
+ async fetchHistory() {
+ await super.fetchHistory();
+ if (this.cachedHistoryOptions.sortBy === "date") {
+ this.#setTodaysDate();
+ }
+ }
+
+ handlePageVisited(event) {
+ const visit = super.handlePageVisited(event);
+ if (!visit) {
+ return;
+ }
+ if (
+ this.cachedHistoryOptions.sortBy === "date" &&
+ (this.#todaysDate == null ||
+ (visit.date.getTime() > this.#todaysDate.getTime() &&
+ !this.#isSameDate(visit.date, this.#todaysDate)))
+ ) {
+ // If today's date has passed (or is null), it should be updated now.
+ this.#setTodaysDate();
+ }
+ }
+
+ #setTodaysDate() {
+ const now = new Date();
+ this.#todaysDate = new Date(
+ now.getFullYear(),
+ now.getMonth(),
+ now.getDate()
+ );
+ this.#yesterdaysDate = new Date(
+ now.getFullYear(),
+ now.getMonth(),
+ now.getDate() - 1
+ );
+ }
+
+ /**
+ * Given two date instances, check if their dates are equivalent.
+ *
+ * @param {Date} dateToCheck
+ * @param {Date} date
+ * @returns {boolean}
+ * Whether both date instances have equivalent dates.
+ */
+ #isSameDate(dateToCheck, date) {
+ return (
+ dateToCheck.getDate() === date.getDate() &&
+ this.#isSameMonth(dateToCheck, date)
+ );
+ }
+
+ /**
+ * Given two date instances, check if their months are equivalent.
+ *
+ * @param {Date} dateToCheck
+ * @param {Date} month
+ * @returns {boolean}
+ * Whether both date instances have equivalent months.
+ */
+ #isSameMonth(dateToCheck, month) {
+ return (
+ dateToCheck.getMonth() === month.getMonth() &&
+ dateToCheck.getFullYear() === month.getFullYear()
+ );
+ }
+}