/* 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 {
html,
ifDefined,
when,
} from "chrome://global/content/vendor/lit.all.mjs";
import {
escapeHtmlEntities,
isSearchEnabled,
navigateToLink,
} from "./helpers.mjs";
import { ViewPage } from "./viewpage.mjs";
// eslint-disable-next-line import/no-unassigned-import
import "chrome://browser/content/migration/migration-wizard.mjs";
// eslint-disable-next-line import/no-unassigned-import
import "chrome://global/content/elements/moz-button.mjs";
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
HistoryController: "resource:///modules/HistoryController.sys.mjs",
ProfileAge: "resource://gre/modules/ProfileAge.sys.mjs",
});
let XPCOMUtils = ChromeUtils.importESModule(
"resource://gre/modules/XPCOMUtils.sys.mjs"
).XPCOMUtils;
const NEVER_REMEMBER_HISTORY_PREF = "browser.privatebrowsing.autostart";
const HAS_IMPORTED_HISTORY_PREF = "browser.migrate.interactions.history";
const IMPORT_HISTORY_DISMISSED_PREF =
"browser.tabs.firefox-view.importHistory.dismissed";
const SEARCH_RESULTS_LIMIT = 300;
class HistoryInView extends ViewPage {
constructor() {
super();
this._started = false;
// Setting maxTabsLength to -1 for no max
this.maxTabsLength = -1;
this.profileAge = 8;
this.fullyUpdated = false;
this.cumulativeSearches = 0;
}
controller = new lazy.HistoryController(this, {
searchResultsLimit: SEARCH_RESULTS_LIMIT,
});
start() {
if (this._started) {
return;
}
this._started = true;
this.controller.updateCache();
this.toggleVisibilityInCardContainer();
}
async connectedCallback() {
super.connectedCallback();
XPCOMUtils.defineLazyPreferenceGetter(
this,
"importHistoryDismissedPref",
IMPORT_HISTORY_DISMISSED_PREF,
false,
() => {
this.requestUpdate();
}
);
XPCOMUtils.defineLazyPreferenceGetter(
this,
"hasImportedHistoryPref",
HAS_IMPORTED_HISTORY_PREF,
false,
() => {
this.requestUpdate();
}
);
if (!this.importHistoryDismissedPref && !this.hasImportedHistoryPrefs) {
let profileAccessor = await lazy.ProfileAge();
let profileCreateTime = await profileAccessor.created;
let timeNow = new Date().getTime();
let profileAge = timeNow - profileCreateTime;
// Convert milliseconds to days
this.profileAge = profileAge / 1000 / 60 / 60 / 24;
}
}
stop() {
if (!this._started) {
return;
}
this._started = false;
this.toggleVisibilityInCardContainer();
}
disconnectedCallback() {
super.disconnectedCallback();
this.stop();
this.migrationWizardDialog?.removeEventListener(
"MigrationWizard:Close",
this.migrationWizardDialog
);
}
viewVisibleCallback() {
this.start();
}
viewHiddenCallback() {
this.stop();
}
static queries = {
cards: { all: "card-container:not([hidden])" },
migrationWizardDialog: "#migrationWizardDialog",
emptyState: "fxview-empty-state",
lists: { all: "fxview-tab-list" },
showAllHistoryBtn: ".show-all-history-button",
searchTextbox: "fxview-search-textbox",
sortInputs: { all: "input[name=history-sort-option]" },
panelList: "panel-list",
};
static properties = {
// Making profileAge a reactive property for testing
profileAge: { type: Number },
};
async getUpdateComplete() {
await super.getUpdateComplete();
await Promise.all(Array.from(this.cards).map(card => card.updateComplete));
}
onPrimaryAction(e) {
navigateToLink(e);
// Record telemetry
Services.telemetry.recordEvent(
"firefoxview_next",
"history",
"visits",
null,
{}
);
if (this.controller.searchQuery) {
const searchesHistogram = Services.telemetry.getKeyedHistogramById(
"FIREFOX_VIEW_CUMULATIVE_SEARCHES"
);
searchesHistogram.add("history", this.cumulativeSearches);
this.cumulativeSearches = 0;
}
}
onSecondaryAction(e) {
this.triggerNode = e.originalTarget;
e.target.querySelector("panel-list").toggle(e.detail.originalEvent);
}
deleteFromHistory(e) {
this.controller.deleteFromHistory();
this.recordContextMenuTelemetry("delete-from-history", e);
}
onChangeSortOption(e) {
this.controller.onChangeSortOption(e);
Services.telemetry.recordEvent(
"firefoxview_next",
"sort_history",
"tabs",
null,
{
sort_type: this.controller.sortOption,
search_start: this.controller.searchQuery ? "true" : "false",
}
);
}
onSearchQuery(e) {
this.controller.onSearchQuery(e);
this.cumulativeSearches = this.controller.searchQuery
? this.cumulativeSearches + 1
: 0;
}
showAllHistory() {
// Record telemetry
Services.telemetry.recordEvent(
"firefoxview_next",
"show_all_history",
"tabs",
null,
{}
);
// Open History view in Library window
this.getWindow().PlacesCommandHook.showPlacesOrganizer("History");
}
async openMigrationWizard() {
let migrationWizardDialog = this.migrationWizardDialog;
if (migrationWizardDialog.open) {
return;
}
await customElements.whenDefined("migration-wizard");
// If we've been opened before, remove the old wizard and insert a
// new one to put it back into its starting state.
if (!migrationWizardDialog.firstElementChild) {
let wizard = document.createElement("migration-wizard");
wizard.toggleAttribute("dialog-mode", true);
migrationWizardDialog.appendChild(wizard);
}
migrationWizardDialog.firstElementChild.requestState();
this.migrationWizardDialog.addEventListener(
"MigrationWizard:Close",
function (e) {
e.currentTarget.close();
}
);
migrationWizardDialog.showModal();
}
shouldShowImportBanner() {
return (
this.profileAge < 8 &&
!this.hasImportedHistoryPref &&
!this.importHistoryDismissedPref
);
}
dismissImportHistory() {
Services.prefs.setBoolPref(IMPORT_HISTORY_DISMISSED_PREF, true);
}
updated() {
this.fullyUpdated = true;
if (this.lists?.length) {
this.toggleVisibilityInCardContainer();
}
}
panelListTemplate() {
return html`
${historyItem.domain}