Backed out changeset 33c08027f6aa (bug 1824826) for causing mochitests failures in test_history.html. CLOSED TREE
This commit is contained in:
@@ -282,6 +282,9 @@ var whitelist = [
|
|||||||
{ file: "chrome://browser/content/screenshots/copy.svg" },
|
{ file: "chrome://browser/content/screenshots/copy.svg" },
|
||||||
{ file: "chrome://browser/content/screenshots/download.svg" },
|
{ file: "chrome://browser/content/screenshots/download.svg" },
|
||||||
{ file: "chrome://browser/content/screenshots/download-white.svg" },
|
{ file: "chrome://browser/content/screenshots/download-white.svg" },
|
||||||
|
|
||||||
|
// Bug 1824826 - Implement a view of history in Firefox View
|
||||||
|
{ file: "resource://gre/modules/PlacesQuery.sys.mjs" },
|
||||||
];
|
];
|
||||||
|
|
||||||
if (AppConstants.NIGHTLY_BUILD && AppConstants.platform != "win") {
|
if (AppConstants.NIGHTLY_BUILD && AppConstants.platform != "win") {
|
||||||
|
|||||||
@@ -23,13 +23,11 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 1px;
|
border-radius: 1px;
|
||||||
outline-offset: 4px;
|
outline-offset: 6px;
|
||||||
padding: 6px;
|
|
||||||
padding-inline-end: 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-container-header[withViewAll] {
|
.card-container-header[withViewAll] {
|
||||||
width: 83%;
|
width: 85%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-container-header[hidden] {
|
.card-container-header[hidden] {
|
||||||
@@ -39,12 +37,10 @@
|
|||||||
.view-all-link {
|
.view-all-link {
|
||||||
color: var(--fxview-primary-action-background);
|
color: var(--fxview-primary-action-background);
|
||||||
float: inline-end;
|
float: inline-end;
|
||||||
outline-offset: 6px;
|
outline-offset: 8px;
|
||||||
border-radius: 1px;
|
border-radius: 1px;
|
||||||
width: 12%;
|
width: 12%;
|
||||||
text-align: end;
|
text-align: end;
|
||||||
padding: 6px;
|
|
||||||
padding-inline-start: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-container-header:focus-visible,
|
.card-container-header:focus-visible,
|
||||||
@@ -103,11 +99,10 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
::slotted([slot=header]) {
|
::slotted(h2) {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 1.13em;
|
font-size: 1.13em;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
user-select: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-container-footer {
|
.card-container-footer {
|
||||||
@@ -118,12 +113,11 @@
|
|||||||
|
|
||||||
::slotted([slot=footer]) {
|
::slotted([slot=footer]) {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
padding-block: 0.5rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 39rem) {
|
@media (max-width: 39rem) {
|
||||||
.card-container-header[withViewAll] {
|
.card-container-header[withViewAll] {
|
||||||
width: 76%;
|
width: 77%;
|
||||||
}
|
}
|
||||||
.view-all-link {
|
.view-all-link {
|
||||||
width: 20%;
|
width: 20%;
|
||||||
|
|||||||
@@ -43,17 +43,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 52rem) {
|
|
||||||
:root {
|
|
||||||
--fxview-sidebar-width: 82px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: var(--fxview-sidebar-width) 1fr;
|
grid-template-columns: var(--fxview-sidebar-width) 1fr;
|
||||||
background-color: var(--fxview-background-color);
|
background-color: var(--fxview-background-color);
|
||||||
color: var(--fxview-text-primary-color);
|
color: var(--fxview-text-primary-color);
|
||||||
|
margin-block-start: var(--fxview-margin-top);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pages {
|
#pages {
|
||||||
@@ -62,17 +57,6 @@ body {
|
|||||||
max-width: 1136px;
|
max-width: 1136px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 120rem) {
|
|
||||||
#pages {
|
|
||||||
margin-inline-start: 148px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-header {
|
|
||||||
margin: 0;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
fxview-category-button[name="overview"]::part(icon) {
|
fxview-category-button[name="overview"]::part(icon) {
|
||||||
background-image: url("chrome://mozapps/skin/extensions/category-discover.svg");
|
background-image: url("chrome://mozapps/skin/extensions/category-discover.svg");
|
||||||
}
|
}
|
||||||
@@ -89,42 +73,14 @@ fxview-category-button[name="history"]::part(icon) {
|
|||||||
background-image: url("chrome://mozapps/skin/extensions/category-discover.svg");
|
background-image: url("chrome://mozapps/skin/extensions/category-discover.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
fxview-tab-list.history::part(secondary-button) {
|
@media (max-width: 52rem) {
|
||||||
background-image: url("chrome://global/skin/icons/more.svg");
|
:root {
|
||||||
|
--fxview-sidebar-width: 82px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sticky-container {
|
@media (min-width: 120rem) {
|
||||||
position: sticky;
|
#pages {
|
||||||
top: 0;
|
margin-inline-start: 148px;
|
||||||
padding-block: var(--fxview-margin-top) 42px;
|
}
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sticky-container.bottom-fade {
|
|
||||||
background:
|
|
||||||
linear-gradient(
|
|
||||||
to bottom,
|
|
||||||
var(--fxview-background-color) 0%,
|
|
||||||
var(--fxview-background-color) 95%,
|
|
||||||
transparent 100%
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
.cards-container {
|
|
||||||
padding-inline: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This should be supported within panel-{item,list} rather than modifying it */
|
|
||||||
panel-item::part(button) {
|
|
||||||
padding-inline-start: 12px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
panel-item::part(button):hover {
|
|
||||||
background-color: var(--fxview-element-background-hover);
|
|
||||||
color: var(--fxview-text-color-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
panel-item::part(button):hover:active {
|
|
||||||
background-color: var(--fxview-element-background-active);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,6 +79,9 @@
|
|||||||
<main id="pages">
|
<main id="pages">
|
||||||
<named-deck>
|
<named-deck>
|
||||||
<view-overview name="overview">
|
<view-overview name="overview">
|
||||||
|
<div>
|
||||||
|
<view-history slot="history"></view-history>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<view-opentabs slot="opentabs"></view-opentabs>
|
<view-opentabs slot="opentabs"></view-opentabs>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,15 +7,13 @@
|
|||||||
margin-inline-start: 42px;
|
margin-inline-start: 42px;
|
||||||
border-inline-end: 1px solid transparent;
|
border-inline-end: 1px solid transparent;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
|
||||||
height: 100vh;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nav {
|
nav {
|
||||||
|
height: 100%;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: min-content 1fr auto;
|
grid-template-rows: min-content 1fr auto;
|
||||||
gap: 25px;
|
gap: 25px;
|
||||||
margin-block-start: var(--fxview-margin-top);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-nav-header {
|
.category-nav-header {
|
||||||
|
|||||||
@@ -195,10 +195,7 @@ export default class FxviewTabList extends MozLitElement {
|
|||||||
: "chrome://browser/content/firefoxview/fxview-tab-list.css";
|
: "chrome://browser/content/firefoxview/fxview-tab-list.css";
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.maxTabsLength > 0) {
|
this.tabItems = this.tabItems.slice(0, this.maxTabsLength);
|
||||||
// Can set maxTabsLength to -1 to have no max
|
|
||||||
this.tabItems = this.tabItems.slice(0, this.maxTabsLength);
|
|
||||||
}
|
|
||||||
const {
|
const {
|
||||||
activeIndex,
|
activeIndex,
|
||||||
currentActiveElementId,
|
currentActiveElementId,
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
/* 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/. */
|
|
||||||
|
|
||||||
.history-sort-options:not([hidden]) {
|
|
||||||
display: flex;
|
|
||||||
gap: 24px;
|
|
||||||
margin-block-start: 35px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.history-sort-option {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.show-all-history-footer {
|
|
||||||
text-align: center;
|
|
||||||
color: var(--fxview-primary-action-background);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.show-all-history-link {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
@@ -5,390 +5,38 @@
|
|||||||
import { html } from "chrome://global/content/vendor/lit.all.mjs";
|
import { html } from "chrome://global/content/vendor/lit.all.mjs";
|
||||||
import { ViewPage } from "./viewpage.mjs";
|
import { ViewPage } from "./viewpage.mjs";
|
||||||
|
|
||||||
const { PlacesQuery } = ChromeUtils.importESModule(
|
|
||||||
"resource://gre/modules/PlacesQuery.sys.mjs"
|
|
||||||
);
|
|
||||||
const { BrowserUtils } = ChromeUtils.importESModule(
|
|
||||||
"resource://gre/modules/BrowserUtils.sys.mjs"
|
|
||||||
);
|
|
||||||
|
|
||||||
function getWindow() {
|
|
||||||
return window.browsingContext.embedderWindowGlobal.browsingContext.window;
|
|
||||||
}
|
|
||||||
|
|
||||||
class HistoryInView extends ViewPage {
|
class HistoryInView extends ViewPage {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.allHistoryItems = [];
|
|
||||||
this.historyMapByDate = [];
|
|
||||||
this.historyMapBySite = [];
|
|
||||||
// Setting maxTabsLength to -1 for no max
|
|
||||||
this.maxTabsLength = -1;
|
|
||||||
this.placesQuery = new PlacesQuery();
|
|
||||||
this.sortOption = "date";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static queries = {
|
connectedCallback() {
|
||||||
cards: { all: "card-container" },
|
|
||||||
};
|
|
||||||
|
|
||||||
async connectedCallback() {
|
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
this.updateHistoryData();
|
|
||||||
this.placesQuery.observeHistory(async newHistory => {
|
|
||||||
await this.updateHistoryData(newHistory);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnectedCallback() {
|
disconnectedCallback() {}
|
||||||
super.disconnectedCallback();
|
|
||||||
this.placesQuery.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
async updateHistoryData(historyData) {
|
|
||||||
if (!historyData) {
|
|
||||||
this.allHistoryItems = await this.placesQuery.getHistory({ daysOld: 60 });
|
|
||||||
} else {
|
|
||||||
this.allHistoryItems = historyData;
|
|
||||||
// Reset history maps before sorting, normalizing, and creating updated maps
|
|
||||||
this.resetHistoryMaps();
|
|
||||||
}
|
|
||||||
this.sortHistoryData();
|
|
||||||
this.normalizeHistoryData();
|
|
||||||
if (this.allHistoryItems.length) {
|
|
||||||
this.createHistoryMaps();
|
|
||||||
}
|
|
||||||
this.requestUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
resetHistoryMaps() {
|
|
||||||
this.historyMapByDate = [];
|
|
||||||
this.historyMapBySite = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
sortHistoryData() {
|
|
||||||
if (this.sortOption == "date" && !this.historyMapByDate.length) {
|
|
||||||
this.allHistoryItems.sort((a, b) => {
|
|
||||||
return new Date(b.date) - new Date(a.date);
|
|
||||||
});
|
|
||||||
} else if (!this.historyMapBySite.length) {
|
|
||||||
this.allHistoryItems.sort((a, b) => {
|
|
||||||
return BrowserUtils.formatURIStringForDisplay(a.url.toLowerCase()) >
|
|
||||||
BrowserUtils.formatURIStringForDisplay(b.url.toLowerCase())
|
|
||||||
? 1
|
|
||||||
: -1;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return this.allHistoryItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
normalizeHistoryData() {
|
|
||||||
// Normalize data for fxview-tabs-list
|
|
||||||
this.allHistoryItems.forEach(historyItem => {
|
|
||||||
historyItem.time = historyItem.date.getTime();
|
|
||||||
historyItem.title = historyItem.title
|
|
||||||
? historyItem.title
|
|
||||||
: historyItem.url;
|
|
||||||
historyItem.icon = `page-icon:${historyItem.url}`;
|
|
||||||
historyItem.primaryL10nId = "fxviewtabrow-tabs-list-tab";
|
|
||||||
historyItem.primaryL10nArgs = JSON.stringify({
|
|
||||||
targetURI: historyItem.url,
|
|
||||||
});
|
|
||||||
historyItem.secondaryL10nId = "fxviewtabrow-open-menu-button";
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
isDateToday(dateObj) {
|
|
||||||
const today = new Date();
|
|
||||||
return (
|
|
||||||
dateObj.getDate() === today.getDate() &&
|
|
||||||
dateObj.getMonth() === today.getMonth() &&
|
|
||||||
dateObj.getFullYear() === today.getFullYear()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
isDateYesterday(dateObj) {
|
|
||||||
const today = new Date();
|
|
||||||
const yesterday = new Date(today);
|
|
||||||
yesterday.setDate(yesterday.getDate() - 1);
|
|
||||||
|
|
||||||
return (
|
|
||||||
dateObj.getDate() === yesterday.getDate() &&
|
|
||||||
dateObj.getMonth() === today.getMonth() &&
|
|
||||||
dateObj.getFullYear() === today.getFullYear()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
isDateThisMonth(dateObj) {
|
|
||||||
const today = new Date();
|
|
||||||
return (
|
|
||||||
!this.isDateToday(dateObj) &&
|
|
||||||
!this.isDateYesterday(dateObj) &&
|
|
||||||
dateObj.getMonth() === today.getMonth() &&
|
|
||||||
dateObj.getFullYear() === today.getFullYear()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
isDatePrevMonth(dateObj) {
|
|
||||||
const today = new Date();
|
|
||||||
return (
|
|
||||||
dateObj.getFullYear() === today.getFullYear() &&
|
|
||||||
dateObj.getMonth() !== today.getMonth()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
createHistoryMaps() {
|
|
||||||
if (this.sortOption === "date" && !this.historyMapByDate.length) {
|
|
||||||
let todayItems = this.allHistoryItems.filter(historyItem =>
|
|
||||||
this.isDateToday(historyItem.date)
|
|
||||||
);
|
|
||||||
if (todayItems.length) {
|
|
||||||
this.historyMapByDate.push({
|
|
||||||
l10nId: "firefoxview-history-date-today",
|
|
||||||
items: todayItems,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
let yesterdayItems = this.allHistoryItems.filter(historyItem =>
|
|
||||||
this.isDateYesterday(historyItem.date)
|
|
||||||
);
|
|
||||||
if (yesterdayItems.length) {
|
|
||||||
this.historyMapByDate.push({
|
|
||||||
l10nId: "firefoxview-history-date-yesterday",
|
|
||||||
items: yesterdayItems,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
let historyThisMonth = this.allHistoryItems.filter(historyItem =>
|
|
||||||
this.isDateThisMonth(historyItem.date)
|
|
||||||
);
|
|
||||||
historyThisMonth.forEach(historyItem => {
|
|
||||||
let historyAtDayThisMonth = historyThisMonth.filter(
|
|
||||||
historyItemThisMonth =>
|
|
||||||
historyItemThisMonth.date.getDate() === historyItem.date.getDate()
|
|
||||||
);
|
|
||||||
if (historyAtDayThisMonth.length) {
|
|
||||||
this.historyMapByDate.push({
|
|
||||||
l10nId: "firefoxview-history-date-this-month",
|
|
||||||
items: historyAtDayThisMonth,
|
|
||||||
});
|
|
||||||
historyThisMonth = historyThisMonth.filter(
|
|
||||||
historyItemThisMonth =>
|
|
||||||
historyItemThisMonth.date.getDate() !== historyItem.date.getDate()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let historyOlderThanThisMonth = this.allHistoryItems.filter(historyItem =>
|
|
||||||
this.isDatePrevMonth(historyItem.date)
|
|
||||||
);
|
|
||||||
historyOlderThanThisMonth.forEach(historyItem => {
|
|
||||||
let items = historyOlderThanThisMonth.filter(
|
|
||||||
historyItemOlderThanThisMonth =>
|
|
||||||
historyItemOlderThanThisMonth.date.getMonth() ===
|
|
||||||
historyItem.date.getMonth()
|
|
||||||
);
|
|
||||||
if (items.length) {
|
|
||||||
this.historyMapByDate.push({
|
|
||||||
l10nId: "firefoxview-history-date-prev-month",
|
|
||||||
items,
|
|
||||||
});
|
|
||||||
historyOlderThanThisMonth = historyOlderThanThisMonth.filter(
|
|
||||||
historyItemOlderThanThisMonth =>
|
|
||||||
historyItemOlderThanThisMonth.date.getMonth() !==
|
|
||||||
historyItem.date.getMonth()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (!this.historyMapBySite.length) {
|
|
||||||
let allHistoryCopy = [...this.allHistoryItems];
|
|
||||||
allHistoryCopy.forEach(historyItem => {
|
|
||||||
let domain = BrowserUtils.formatURIStringForDisplay(historyItem.url);
|
|
||||||
let items = allHistoryCopy.filter(
|
|
||||||
historyCopyItem =>
|
|
||||||
BrowserUtils.formatURIStringForDisplay(historyCopyItem.url) ===
|
|
||||||
domain
|
|
||||||
);
|
|
||||||
if (items.length) {
|
|
||||||
this.historyMapBySite.push({
|
|
||||||
domain,
|
|
||||||
items,
|
|
||||||
});
|
|
||||||
allHistoryCopy = allHistoryCopy.filter(
|
|
||||||
historyCopyItem =>
|
|
||||||
BrowserUtils.formatURIStringForDisplay(historyCopyItem.url) !==
|
|
||||||
domain
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onPrimaryAction(e) {
|
|
||||||
let currentWindow = getWindow();
|
|
||||||
if (currentWindow.openTrustedLinkIn) {
|
|
||||||
let where = BrowserUtils.whereToOpenLink(
|
|
||||||
e.detail.originalEvent,
|
|
||||||
false,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
if (where == "current") {
|
|
||||||
where = "tab";
|
|
||||||
}
|
|
||||||
currentWindow.openTrustedLinkIn(e.originalTarget.url, where);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onSecondaryAction(e) {
|
|
||||||
e.target.querySelector("panel-list").toggle(e.detail.originalEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
async toggleSortOption(e) {
|
|
||||||
this.sortOption = e.target.value;
|
|
||||||
this.updateHistoryData();
|
|
||||||
}
|
|
||||||
|
|
||||||
showAllHistory() {
|
|
||||||
// Open History view in Library window
|
|
||||||
getWindow().PlacesCommandHook.showPlacesOrganizer("History");
|
|
||||||
}
|
|
||||||
|
|
||||||
panelListTemplate() {
|
|
||||||
return html`
|
|
||||||
<panel-list slot="menu">
|
|
||||||
<panel-item data-l10n-id="fxviewtabrow-delete"></panel-item>
|
|
||||||
<panel-item
|
|
||||||
data-l10n-id="fxviewtabrow-forget-about-this-site"
|
|
||||||
></panel-item>
|
|
||||||
<hr />
|
|
||||||
<panel-item data-l10n-id="fxviewtabrow-open-in-window"></panel-item>
|
|
||||||
<panel-item
|
|
||||||
data-l10n-id="fxviewtabrow-open-in-private-window"
|
|
||||||
></panel-item>
|
|
||||||
<hr />
|
|
||||||
<panel-item data-l10n-id="fxviewtabrow-add-bookmark"></panel-item>
|
|
||||||
<panel-item data-l10n-id="fxviewtabrow-save-to-pocket"></panel-item>
|
|
||||||
<panel-item data-l10n-id="fxviewtabrow-copy-link"></panel-item>
|
|
||||||
</panel-list>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
historyCardsTemplate() {
|
|
||||||
let cardsTemplate = [];
|
|
||||||
if (this.sortOption === "date" && this.historyMapByDate.length) {
|
|
||||||
this.historyMapByDate.forEach((historyItem, index) => {
|
|
||||||
if (historyItem.items.length) {
|
|
||||||
let dateArg = JSON.stringify({ date: historyItem.items[0].time });
|
|
||||||
cardsTemplate.push(html`<card-container>
|
|
||||||
<h2
|
|
||||||
slot="header"
|
|
||||||
data-l10n-id=${historyItem.l10nId}
|
|
||||||
data-l10n-args=${dateArg}
|
|
||||||
></h2>
|
|
||||||
<fxview-tab-list
|
|
||||||
slot="main"
|
|
||||||
class="history"
|
|
||||||
dateTimeFormat=${historyItem.l10nId.includes("prev-month")
|
|
||||||
? "dateTime"
|
|
||||||
: "time"}
|
|
||||||
hasPopup="menu"
|
|
||||||
maxTabsLength=${this.maxTabsLength}
|
|
||||||
.tabItems=${historyItem.items}
|
|
||||||
@fxview-tab-list-primary-action=${this.onPrimaryAction}
|
|
||||||
@fxview-tab-list-secondary-action=${this.onSecondaryAction}
|
|
||||||
>
|
|
||||||
${this.panelListTemplate()}
|
|
||||||
</fxview-tab-list>
|
|
||||||
</card-container>`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (this.historyMapBySite.length) {
|
|
||||||
this.historyMapBySite.forEach(historyItem => {
|
|
||||||
if (historyItem.items.length) {
|
|
||||||
cardsTemplate.push(html`<card-container>
|
|
||||||
<h2 slot="header">${historyItem.domain}</h2>
|
|
||||||
<fxview-tab-list
|
|
||||||
slot="main"
|
|
||||||
class="history"
|
|
||||||
dateTimeFormat="dateTime"
|
|
||||||
hasPopup="menu"
|
|
||||||
maxTabsLength=${this.maxTabsLength}
|
|
||||||
.tabItems=${historyItem.items}
|
|
||||||
@fxview-tab-list-primary-action=${this.onPrimaryAction}
|
|
||||||
@fxview-tab-list-secondary-action=${this.onSecondaryAction}
|
|
||||||
>
|
|
||||||
${this.panelListTemplate()}
|
|
||||||
</fxview-tab-list>
|
|
||||||
</card-container>`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return cardsTemplate;
|
|
||||||
}
|
|
||||||
|
|
||||||
emptyMessageTemplate() {
|
|
||||||
// TO-DO: Bug 1826604 - Add History empty states and banner
|
|
||||||
return html`
|
|
||||||
<card-container hideHeader="true" class"empty-state history">
|
|
||||||
<p slot="main">EMPTY MESSAGE</p>
|
|
||||||
</card-container>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (!this.selectedTab) {
|
if (!this.selectedTab && !this.overview) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
let numRows = this.overview ? 5 : 10;
|
||||||
|
const itemTemplates = [];
|
||||||
|
|
||||||
|
for (let i = 1; i <= numRows; i++) {
|
||||||
|
itemTemplates.push(html` <p>History Row ${i}</p> `);
|
||||||
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<link
|
<card-container
|
||||||
rel="stylesheet"
|
.viewAllPage=${this.overview ? "history" : null}
|
||||||
href="chrome://browser/content/firefoxview/firefoxview-next.css"
|
?preserveCollapseState=${this.overview ? true : null}
|
||||||
/>
|
>
|
||||||
<link
|
<h2 slot="header" data-l10n-id="firefoxview-history-header"></h2>
|
||||||
rel="stylesheet"
|
<ul slot="main">
|
||||||
href="chrome://browser/content/firefoxview/history.css"
|
${itemTemplates}
|
||||||
/>
|
</ul>
|
||||||
<div class="sticky-container bottom-fade">
|
</card-container>
|
||||||
<h2 class="page-header" data-l10n-id="firefoxview-history-header"></h2>
|
|
||||||
<span class="history-sort-options">
|
|
||||||
<div class="history-sort-option">
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
id="sort-by-date"
|
|
||||||
name="history-sort-option"
|
|
||||||
value="date"
|
|
||||||
checked
|
|
||||||
@click=${this.toggleSortOption}
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
for="sort-by-date"
|
|
||||||
data-l10n-id="firefoxview-sort-history-by-date-label"
|
|
||||||
></label>
|
|
||||||
</div>
|
|
||||||
<div class="history-sort-option">
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name="history-sort-option"
|
|
||||||
value="site"
|
|
||||||
@click=${this.toggleSortOption}
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
for="sort-by-site"
|
|
||||||
data-l10n-id="firefoxview-sort-history-by-site-label"
|
|
||||||
></label>
|
|
||||||
</div>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="cards-container">
|
|
||||||
${!this.allHistoryItems.length
|
|
||||||
? this.emptyMessageTemplate()
|
|
||||||
: this.historyCardsTemplate()}
|
|
||||||
</div>
|
|
||||||
<div class="show-all-history-footer">
|
|
||||||
<span
|
|
||||||
class="show-all-history-link"
|
|
||||||
data-l10n-id="firefoxview-show-all-history"
|
|
||||||
@click=${this.showAllHistory}
|
|
||||||
></span>
|
|
||||||
</div>
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ browser.jar:
|
|||||||
content/browser/firefoxview/firefoxview-next.html
|
content/browser/firefoxview/firefoxview-next.html
|
||||||
content/browser/firefoxview/firefoxview.mjs
|
content/browser/firefoxview/firefoxview.mjs
|
||||||
content/browser/firefoxview/firefoxview-next.mjs
|
content/browser/firefoxview/firefoxview-next.mjs
|
||||||
content/browser/firefoxview/history.css
|
|
||||||
content/browser/firefoxview/history.mjs
|
content/browser/firefoxview/history.mjs
|
||||||
content/browser/firefoxview/opentabs.mjs
|
content/browser/firefoxview/opentabs.mjs
|
||||||
content/browser/firefoxview/view-opentabs.css
|
content/browser/firefoxview/view-opentabs.css
|
||||||
|
|||||||
@@ -113,20 +113,13 @@ class OpenTabsInView extends ViewPage {
|
|||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="chrome://browser/content/firefoxview/view-opentabs.css"
|
href="chrome://browser/content/firefoxview/view-opentabs.css"
|
||||||
/>
|
/>
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
href="chrome://browser/content/firefoxview/firefoxview-next.css"
|
|
||||||
/>
|
|
||||||
<div class="sticky-container bottom-fade">
|
|
||||||
<h2 class="page-header" data-l10n-id="firefoxview-opentabs-header"></h2>
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
class="${classMap({
|
class=${classMap({
|
||||||
"view-opentabs-card-container": true,
|
"view-opentabs-card-container": true,
|
||||||
"one-column": this.windows.size <= 1,
|
"one-column": this.windows.size <= 1,
|
||||||
"two-columns": this.windows.size === 2,
|
"two-columns": this.windows.size === 2,
|
||||||
"three-columns": this.windows.size >= 3,
|
"three-columns": this.windows.size >= 3,
|
||||||
})} cards-container"
|
})}
|
||||||
>
|
>
|
||||||
${when(
|
${when(
|
||||||
currentWindowIndex && currentWindowTabs,
|
currentWindowIndex && currentWindowTabs,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
import { html } from "chrome://global/content/vendor/lit.all.mjs";
|
import { css, html } from "chrome://global/content/vendor/lit.all.mjs";
|
||||||
import { ViewPage } from "./viewpage.mjs";
|
import { ViewPage } from "./viewpage.mjs";
|
||||||
|
|
||||||
class OverviewInView extends ViewPage {
|
class OverviewInView extends ViewPage {
|
||||||
@@ -17,19 +17,19 @@ class OverviewInView extends ViewPage {
|
|||||||
|
|
||||||
disconnectedCallback() {}
|
disconnectedCallback() {}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
div {
|
||||||
|
border: 1px solid black;
|
||||||
|
border-radius: 10px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return html`
|
return html` <slot></slot> `;
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
href="chrome://browser/content/firefoxview/firefoxview-next.css"
|
|
||||||
/>
|
|
||||||
<div class="sticky-container bottom-fade">
|
|
||||||
<h2 class="page-header" data-l10n-id="firefoxview-overview-header"></h2>
|
|
||||||
</div>
|
|
||||||
<div class="cards-container">
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
customElements.define("view-overview", OverviewInView);
|
customElements.define("view-overview", OverviewInView);
|
||||||
|
|||||||
@@ -3,5 +3,4 @@
|
|||||||
[test_card_container.html]
|
[test_card_container.html]
|
||||||
[test_fxview_category_navigation.html]
|
[test_fxview_category_navigation.html]
|
||||||
[test_fxview_tab_list.html]
|
[test_fxview_tab_list.html]
|
||||||
[test_history.html]
|
|
||||||
[test_opentabs.html]
|
[test_opentabs.html]
|
||||||
|
|||||||
@@ -1,146 +0,0 @@
|
|||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>History Tests</title>
|
|
||||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
|
||||||
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
|
||||||
<link rel="stylesheet" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
|
||||||
<link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
|
|
||||||
<link rel="stylesheet" href="chrome://browser/content/firefoxview/firefoxview-next.css"/>
|
|
||||||
<link rel="localization" href="browser/firefoxView.ftl"/>
|
|
||||||
<script type="module" src="chrome://browser/content/firefoxview/history.mjs"></script>
|
|
||||||
<script type="module" src="chrome://browser/content/firefoxview/overview.mjs"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<style>
|
|
||||||
</style>
|
|
||||||
<p id="display"></p>
|
|
||||||
<div id="content">
|
|
||||||
<view-history></view-history>
|
|
||||||
</div>
|
|
||||||
<pre id="test">
|
|
||||||
<script class="testbody" type="application/javascript">
|
|
||||||
const { PlacesQuery } = ChromeUtils.importESModule(
|
|
||||||
"resource://gre/modules/PlacesQuery.sys.mjs"
|
|
||||||
);
|
|
||||||
const { PromiseUtils } = ChromeUtils.importESModule(
|
|
||||||
"resource://gre/modules/PromiseUtils.sys.mjs"
|
|
||||||
);
|
|
||||||
const { PlacesUtils } = ChromeUtils.importESModule(
|
|
||||||
"resource://gre/modules/PlacesUtils.sys.mjs"
|
|
||||||
);
|
|
||||||
const { TestUtils } = ChromeUtils.import(
|
|
||||||
"resource://testing-common/TestUtils.jsm"
|
|
||||||
);
|
|
||||||
|
|
||||||
const historyComponent = document.querySelector("view-history");
|
|
||||||
const URLs = [
|
|
||||||
"http://mochi.test:8888/browser/",
|
|
||||||
"https://www.example.com/",
|
|
||||||
"https://example.net/",
|
|
||||||
"https://example.org/",
|
|
||||||
"https://www.mozilla.org/"
|
|
||||||
];
|
|
||||||
|
|
||||||
async function addHistoryItems(dateAdded) {
|
|
||||||
await PlacesUtils.history.insert({
|
|
||||||
url: URLs[0],
|
|
||||||
title: "Example Domain 1",
|
|
||||||
visits: [{ date: dateAdded }],
|
|
||||||
});
|
|
||||||
await PlacesUtils.history.insert({
|
|
||||||
url: URLs[1],
|
|
||||||
title: "Example Domain 2",
|
|
||||||
visits: [{ date: dateAdded }],
|
|
||||||
});
|
|
||||||
await PlacesUtils.history.insert({
|
|
||||||
url: URLs[2],
|
|
||||||
title: "Example Domain 3",
|
|
||||||
visits: [{ date: dateAdded }],
|
|
||||||
});
|
|
||||||
await PlacesUtils.history.insert({
|
|
||||||
url: URLs[3],
|
|
||||||
title: "Example Domain 4",
|
|
||||||
visits: [{ date: dateAdded }],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const placesQuery = new PlacesQuery();
|
|
||||||
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
||||||
const today = new Date();
|
|
||||||
const yesterday = new Date(Date.now() - DAY_MS);
|
|
||||||
const twoDaysAgo = new Date(Date.now() - DAY_MS * 2);
|
|
||||||
const threeDaysAgo = new Date(Date.now() - DAY_MS * 3);
|
|
||||||
const fourDaysAgo = new Date(Date.now() - DAY_MS * 4);
|
|
||||||
const oneMonthAgo = new Date(today);
|
|
||||||
oneMonthAgo.setMonth(oneMonthAgo.getMonth() === 0 ? 11 : oneMonthAgo.getMonth() - 1);
|
|
||||||
// Total number of cards should be 6 if today's date is at least the 5th
|
|
||||||
let expectedNumOfCards = today.getDate() < 5 ? 6 - (5 - today.getDate()) : 6;
|
|
||||||
|
|
||||||
add_setup(async function setup() {
|
|
||||||
await PlacesUtils.history.clear();
|
|
||||||
await addHistoryItems(today);
|
|
||||||
await addHistoryItems(yesterday);
|
|
||||||
await addHistoryItems(twoDaysAgo);
|
|
||||||
await addHistoryItems(threeDaysAgo);
|
|
||||||
await addHistoryItems(fourDaysAgo);
|
|
||||||
await addHistoryItems(oneMonthAgo);
|
|
||||||
let history = await placesQuery.getHistory();
|
|
||||||
is(
|
|
||||||
history.length,
|
|
||||||
24,
|
|
||||||
"There should be 24 total history items"
|
|
||||||
);
|
|
||||||
historyComponent.enter();
|
|
||||||
await historyComponent.getUpdateComplete();
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that history data is grouped by date or site
|
|
||||||
*/
|
|
||||||
add_task(async function test_history_grouping() {
|
|
||||||
await historyComponent.getUpdateComplete();
|
|
||||||
// Ensure all expected cards are rendered before beginning tests
|
|
||||||
await TestUtils.waitForCondition(() => historyComponent.cards.length === expectedNumOfCards);
|
|
||||||
let cards = historyComponent.cards;
|
|
||||||
await Promise.all(Array.from(cards).map(card =>
|
|
||||||
TestUtils.waitForCondition(() => card.querySelector("[slot=header]").textContent.length)
|
|
||||||
));
|
|
||||||
let actualNumOfCards = cards.length;
|
|
||||||
|
|
||||||
is(
|
|
||||||
actualNumOfCards,
|
|
||||||
expectedNumOfCards,
|
|
||||||
`Total number of cards should be ${expectedNumOfCards}`
|
|
||||||
)
|
|
||||||
|
|
||||||
let firstCard = cards[0];
|
|
||||||
let firstCardHeaderText = firstCard.querySelector("[slot=header]").textContent;
|
|
||||||
|
|
||||||
ok(
|
|
||||||
firstCardHeaderText.includes("Today"),
|
|
||||||
"The first card has a header for 'Today'."
|
|
||||||
);
|
|
||||||
|
|
||||||
// Test number of cards when sorted by site/domain
|
|
||||||
historyComponent.sortOption = "site";
|
|
||||||
await historyComponent.updateHistoryData();
|
|
||||||
await historyComponent.getUpdateComplete();
|
|
||||||
|
|
||||||
expectedNumOfCards = 4;
|
|
||||||
actualNumOfCards = historyComponent.shadowRoot.querySelectorAll("card-container").length;
|
|
||||||
|
|
||||||
is(
|
|
||||||
expectedNumOfCards,
|
|
||||||
actualNumOfCards,
|
|
||||||
`Total number of cards should be ${expectedNumOfCards}`
|
|
||||||
)
|
|
||||||
|
|
||||||
await PlacesUtils.history.clear();
|
|
||||||
placesQuery.close();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</pre>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -72,7 +72,7 @@ You'll need to pass along some of the following properties:
|
|||||||
* `time` (Ex: "4:00 PM", "16:00", etc - Will be formatted based on locale)
|
* `time` (Ex: "4:00 PM", "16:00", etc - Will be formatted based on locale)
|
||||||
* `dateTime` (Ex: "4/1/23 4:00PM", "01/04/23 16:00", etc. - Will be formatted based on locale)
|
* `dateTime` (Ex: "4/1/23 4:00PM", "01/04/23 16:00", etc. - Will be formatted based on locale)
|
||||||
* `hasPopup` (**Optional**): The optional aria-haspopup attribute for the secondary action, if required
|
* `hasPopup` (**Optional**): The optional aria-haspopup attribute for the secondary action, if required
|
||||||
* `maxTabsLength` (**Optional**): The max number of tabs you want to display in the tabs list. The default value will be `25` if no max value is given. You may use any negative number such as `-1` to indicate no max.
|
* `maxTabsLength` (**Optional**): The max number of tabs you want to display in the tabs list. The default value will be `25` if no max value is given.
|
||||||
* `tabItems` (**Required**): An array of tab data such as History nodes, Bookmark nodes, Synced Tabs, etc.
|
* `tabItems` (**Required**): An array of tab data such as History nodes, Bookmark nodes, Synced Tabs, etc.
|
||||||
* The component is expecting to receive the following properties within each `tabItems` object (you may need to do some normalizing for this):
|
* The component is expecting to receive the following properties within each `tabItems` object (you may need to do some normalizing for this):
|
||||||
* `icon` (**Required**) - The location string for the favicon. Will fallback to default favicon if none is found.
|
* `icon` (**Required**) - The location string for the favicon. Will fallback to default favicon if none is found.
|
||||||
|
|||||||
@@ -112,8 +112,6 @@ firefoxview-collapse-button-hide =
|
|||||||
|
|
||||||
firefoxview-overview-nav = Recent browsing
|
firefoxview-overview-nav = Recent browsing
|
||||||
.title = Recent browsing
|
.title = Recent browsing
|
||||||
firefoxview-overview-header = Recent browsing
|
|
||||||
.title = Recent browsing
|
|
||||||
|
|
||||||
## History in this context refers to browser history
|
## History in this context refers to browser history
|
||||||
|
|
||||||
@@ -159,18 +157,3 @@ firefoxview-opentabs-focus-tab =
|
|||||||
|
|
||||||
firefoxview-show-more = Show more
|
firefoxview-show-more = Show more
|
||||||
firefoxview-show-less = Show less
|
firefoxview-show-less = Show less
|
||||||
|
|
||||||
firefoxview-sort-history-by-date-label = Sort by date
|
|
||||||
firefoxview-sort-history-by-site-label = Sort by site
|
|
||||||
|
|
||||||
## Variables:
|
|
||||||
## $date (string) - Date to be formatted based on locale
|
|
||||||
|
|
||||||
firefoxview-history-date-today = Today - { DATETIME($date, dateStyle: "full") }
|
|
||||||
firefoxview-history-date-yesterday = Yesterday - { DATETIME($date, dateStyle: "full") }
|
|
||||||
firefoxview-history-date-this-month = { DATETIME($date, dateStyle: "full") }
|
|
||||||
firefoxview-history-date-prev-month = { DATETIME($date, month: "long", year: "numeric") }
|
|
||||||
|
|
||||||
##
|
|
||||||
|
|
||||||
firefoxview-show-all-history = Show all history
|
|
||||||
|
|||||||
Reference in New Issue
Block a user