mirror of
https://github.com/zen-browser/desktop.git
synced 2026-09-08 06:17:19 +00:00
no-bug: Small changes
This commit is contained in:
@@ -86,11 +86,18 @@ export class ZenLibrary extends MozLitElement {
|
||||
this.addEventListener("animationend", this);
|
||||
// Add connected call back and make `appContentWrapper` transform translate the oposite of this element
|
||||
this.#resizeObserver = new ResizeObserver(() => {
|
||||
if (this._swipeActive) {
|
||||
this._swipeWrapperTargetPx = this.#computeWrapperTargetPx();
|
||||
ZenLibrary.updateSwipeProgress(this._swipeProgress ?? 0);
|
||||
return;
|
||||
}
|
||||
if (gZenWorkspaces._swipeManager._swipeState.librarySwiping) {
|
||||
return;
|
||||
}
|
||||
let translateX = this.#computeWrapperTargetPx();
|
||||
lazy.appContentWrapper.style.transform = `translateX(${translateX}px)`;
|
||||
requestAnimationFrame(() => {
|
||||
lazy.appContentWrapper.style.transform = `translateX(${translateX}px)`;
|
||||
});
|
||||
});
|
||||
this.#resizeObserver.observe(this);
|
||||
for (const Section of Object.values(lazy.ZenLibrarySections)) {
|
||||
@@ -221,7 +228,7 @@ export class ZenLibrary extends MozLitElement {
|
||||
break;
|
||||
}
|
||||
case "animationend": {
|
||||
if (event.animationName === "zen-library-tab-icon-play") {
|
||||
if (event.animationName === "zen-library-sprite-play") {
|
||||
event.target.closest(".zen-library-tab")?.removeAttribute("animate");
|
||||
}
|
||||
break;
|
||||
@@ -313,9 +320,12 @@ export class ZenLibrary extends MozLitElement {
|
||||
*/
|
||||
#computeWrapperTargetPx() {
|
||||
const isRightSide = gZenVerticalTabsManager._prefsRightSide;
|
||||
let translateX = this.getBoundingClientRect()[
|
||||
isRightSide ? "left" : "right"
|
||||
];
|
||||
const selfTransform = getComputedStyle(this).transform;
|
||||
const selfOffset =
|
||||
selfTransform === "none" ? 0 : new DOMMatrix(selfTransform).m41;
|
||||
let translateX =
|
||||
this.getBoundingClientRect()[isRightSide ? "left" : "right"] -
|
||||
selfOffset;
|
||||
const contentPosition = window.windowUtils.getBoundsWithoutFlushing(
|
||||
lazy.appContentWrapper
|
||||
)[isRightSide ? "right" : "left"];
|
||||
@@ -396,21 +406,11 @@ export class ZenLibrary extends MozLitElement {
|
||||
instance.#cancelActiveAnimations();
|
||||
const wasOpen = instance.hasAttribute("open");
|
||||
if (wasOpen) {
|
||||
// Library is already open; the wrapper's current inline transform IS
|
||||
// the target — no remeasure needed.
|
||||
instance._swipeWrapperTargetPx =
|
||||
new DOMMatrix(lazy.appContentWrapper.style.transform).m41 ||
|
||||
instance.#computeWrapperTargetPx();
|
||||
} else {
|
||||
// Measure the open-state wrapper target without flashing: temporarily
|
||||
// mark [open] so layout reflects the open position, then revert.
|
||||
instance.setAttribute("open", "true");
|
||||
instance.style.visibility = "hidden";
|
||||
await new Promise(r => requestAnimationFrame(r));
|
||||
instance._swipeWrapperTargetPx = instance.#computeWrapperTargetPx();
|
||||
instance.style.visibility = "";
|
||||
instance.removeAttribute("open");
|
||||
lazy.appContentWrapper.style.transform = "";
|
||||
}
|
||||
instance._swipeActive = true;
|
||||
// Initialize visual state to match the current attribute.
|
||||
|
||||
@@ -475,21 +475,18 @@ class SearchSection extends LibrarySection {
|
||||
}
|
||||
|
||||
/**
|
||||
* Open `url` in a Glance overlay anchored to the clicked item.
|
||||
* Open `url` in a Glance overlay.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {string} url
|
||||
*/
|
||||
_openInGlance(event, url) {
|
||||
const itemEl = event.currentTarget;
|
||||
const rect = window.windowUtils.getBoundsWithoutFlushing(itemEl);
|
||||
_openInGlance(url) {
|
||||
const tabPanelRect = window.windowUtils.getBoundsWithoutFlushing(
|
||||
window.gBrowser.tabpanels
|
||||
);
|
||||
window.gZenGlanceManager.openGlance({
|
||||
url,
|
||||
clientX: rect.left - tabPanelRect.left,
|
||||
clientY: rect.top - tabPanelRect.top,
|
||||
clientX: window.innerWidth / 2 - tabPanelRect.left,
|
||||
clientY: window.innerHeight / 2 - tabPanelRect.top,
|
||||
width: 0,
|
||||
height: 0,
|
||||
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
@@ -515,6 +512,26 @@ class SearchSection extends LibrarySection {
|
||||
return html``;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shared empty-state markup: the section's sprite icon above the localized
|
||||
* message. The [data-section] attribute picks the sprite strip, see
|
||||
* zen-library.css.
|
||||
*
|
||||
* @param {string} emptyL10nId - message shown when the section has no data.
|
||||
*/
|
||||
_renderEmptyState(emptyL10nId) {
|
||||
return html`
|
||||
<div class="empty-state" data-section=${this.constructor.id}>
|
||||
<div class="empty-state-icon">
|
||||
<div class="empty-state-icon-image"></div>
|
||||
</div>
|
||||
<label
|
||||
data-l10n-id=${this.searchTerm ? "library-search-no-results" : emptyL10nId}
|
||||
></label>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
render() {
|
||||
const hasFilters = !!this._filters().length;
|
||||
return html`
|
||||
@@ -917,12 +934,7 @@ class ZenLibraryHistorySection extends ProgressiveSearchSection {
|
||||
return html``;
|
||||
}
|
||||
if (this.isEmpty) {
|
||||
return html`
|
||||
<div
|
||||
class="empty-state"
|
||||
data-l10n-id=${this.searchTerm ? "library-search-no-results" : "library-history-empty"}
|
||||
></div>
|
||||
`;
|
||||
return this._renderEmptyState("library-history-empty");
|
||||
}
|
||||
|
||||
const slice = this._getRenderedSlice();
|
||||
@@ -960,9 +972,7 @@ class ZenLibraryHistorySection extends ProgressiveSearchSection {
|
||||
}
|
||||
|
||||
/**
|
||||
* Plain click on a history row opens the page in a Glance overlay; holding
|
||||
* Ctrl (or any other modifier / middle-click) falls back to the standard
|
||||
* "where to open" routing.
|
||||
* Clicking a history row opens the page in a new tab.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {object} item
|
||||
@@ -976,21 +986,6 @@ class ZenLibraryHistorySection extends ProgressiveSearchSection {
|
||||
}
|
||||
event.preventDefault();
|
||||
|
||||
const hasModifier =
|
||||
event.ctrlKey || event.metaKey || event.shiftKey || event.altKey;
|
||||
const isMiddleClick = event.button === 1;
|
||||
|
||||
if (
|
||||
!hasModifier &&
|
||||
!isMiddleClick &&
|
||||
Services.prefs.getBoolPref("zen.glance.enabled", true)
|
||||
) {
|
||||
// Glance overlays on top of the library; keep the library open so the
|
||||
// user can fire another glance without re-opening it.
|
||||
this._openInGlance(event, item.url);
|
||||
return;
|
||||
}
|
||||
|
||||
const where = lazy.BrowserUtils.whereToOpenLink(event, false, true);
|
||||
window.openTrustedLinkIn(item.url, where === "current" ? "tab" : where);
|
||||
this._closeLibrary();
|
||||
@@ -1031,15 +1026,6 @@ class ZenLibraryHistorySection extends ProgressiveSearchSection {
|
||||
this._closeLibrary();
|
||||
},
|
||||
},
|
||||
{
|
||||
l10nId: "library-item-context-open-glance",
|
||||
onClick: () => {
|
||||
// Use the section element as the anchor — context menu opens at
|
||||
// the cursor and the original item element isn't tracked here.
|
||||
const fakeEvent = { currentTarget: this };
|
||||
this._openInGlance(fakeEvent, item.url);
|
||||
},
|
||||
},
|
||||
{
|
||||
l10nId: "library-item-context-open-new-window",
|
||||
onClick: () => {
|
||||
@@ -1177,12 +1163,7 @@ class ZenLibraryDownloadsSection extends ProgressiveSearchSection {
|
||||
const slice = this._getRenderedSlice();
|
||||
|
||||
if (this.isEmpty) {
|
||||
return html`
|
||||
<div
|
||||
class="empty-state"
|
||||
data-l10n-id=${this.searchTerm ? "library-search-no-results" : "library-downloads-empty"}
|
||||
></div>
|
||||
`;
|
||||
return this._renderEmptyState("library-downloads-empty");
|
||||
}
|
||||
|
||||
const groups = this.#groupByDate(slice);
|
||||
@@ -1313,7 +1294,7 @@ class ZenLibraryDownloadsSection extends ProgressiveSearchSection {
|
||||
const previewUrl =
|
||||
dl.source.referrerInfo?.originalReferrer?.spec || dl.source.url;
|
||||
if (previewUrl) {
|
||||
this._openInGlance(event, previewUrl);
|
||||
this._openInGlance(previewUrl);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1631,12 +1612,7 @@ class ZenLibraryBoostsSection extends SearchSection {
|
||||
renderSearchResults() {
|
||||
const boosts = this.#getBoosts();
|
||||
if (boosts.length === 0) {
|
||||
return html`
|
||||
<div
|
||||
class="empty-state"
|
||||
data-l10n-id=${this.searchTerm ? "library-search-no-results" : "library-boosts-empty"}
|
||||
></div>
|
||||
`;
|
||||
return this._renderEmptyState("library-boosts-empty");
|
||||
}
|
||||
return html`${boosts.map(b => this.#renderBoost(b))}`;
|
||||
}
|
||||
@@ -1647,7 +1623,7 @@ class ZenLibraryBoostsSection extends SearchSection {
|
||||
class="library-item library-boost-item"
|
||||
data-key=${`${boost.domain}|${boost.id}`}
|
||||
?active=${boost.isActive}
|
||||
@click=${e => this.#openBoost(e, boost)}
|
||||
@click=${() => this.#openBoost(boost)}
|
||||
@contextmenu=${e => this._onItemContextMenu(e, boost)}
|
||||
>
|
||||
<div class="library-item-stack">
|
||||
@@ -1693,12 +1669,11 @@ class ZenLibraryBoostsSection extends SearchSection {
|
||||
* Open the boost's domain in a Glance overlay and pop the boost editor
|
||||
* window next to it so the user can tweak the boost while previewing.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {object} boost
|
||||
*/
|
||||
#openBoost(event, boost) {
|
||||
#openBoost(boost) {
|
||||
const url = `https://${boost.domain}/`;
|
||||
this._openInGlance(event, url);
|
||||
this._openInGlance(url);
|
||||
try {
|
||||
const stored = lazy.gZenBoostsManager.loadBoostFromStore(
|
||||
boost.domain,
|
||||
|
||||
@@ -83,6 +83,8 @@ zen-library[open] {
|
||||
}
|
||||
|
||||
.zen-library-tab {
|
||||
--zen-library-sprite-size: 28px;
|
||||
|
||||
display: flex;
|
||||
position: relative;
|
||||
justify-content: center;
|
||||
@@ -114,54 +116,56 @@ zen-library[open] {
|
||||
}
|
||||
|
||||
& .zen-library-tab-icon {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
width: var(--zen-library-sprite-size);
|
||||
height: var(--zen-library-sprite-size);
|
||||
overflow: clip;
|
||||
}
|
||||
|
||||
& .zen-library-tab-icon-image {
|
||||
width: calc(36 * 28px);
|
||||
height: 28px;
|
||||
fill: rgba(255, 255, 255, 0.8);
|
||||
stroke: var(--zen-colors-primary);
|
||||
-moz-context-properties: fill, stroke;
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
&[data-section="history"] .zen-library-tab-icon-image {
|
||||
background-image: url("chrome://browser/skin/zen-icons/library/library-history-sprite.svg");
|
||||
}
|
||||
|
||||
&[data-section="downloads"] .zen-library-tab-icon-image {
|
||||
background-image: url("chrome://browser/skin/zen-icons/library/library-downloads-sprite.svg");
|
||||
}
|
||||
|
||||
&[data-section="boosts"] .zen-library-tab-icon-image {
|
||||
background-image: url("chrome://browser/skin/zen-icons/library/library-boosts-sprite.svg");
|
||||
}
|
||||
|
||||
&[data-section="spaces"] .zen-library-tab-icon-image {
|
||||
background-image: url("chrome://browser/skin/zen-icons/library/library-spaces-sprite.svg");
|
||||
}
|
||||
|
||||
&[data-section="media"] .zen-library-tab-icon-image {
|
||||
background-image: url("chrome://browser/skin/zen-icons/library/library-media-sprite.svg");
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
&[animate] .zen-library-tab-icon-image {
|
||||
animation: zen-library-tab-icon-play 0.583s steps(36, jump-none);
|
||||
animation: zen-library-sprite-play 0.583s steps(36, jump-none);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zen-library-tab-icon-play {
|
||||
.zen-library-tab-icon-image,
|
||||
.empty-state-icon-image {
|
||||
width: calc(36 * var(--zen-library-sprite-size));
|
||||
height: var(--zen-library-sprite-size);
|
||||
background-size: 100% 100%;
|
||||
fill: rgba(255, 255, 255, 0.8);
|
||||
stroke: var(--zen-colors-primary);
|
||||
-moz-context-properties: fill, stroke;
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
[data-section="history"] :is(.zen-library-tab-icon-image, .empty-state-icon-image) {
|
||||
background-image: url("chrome://browser/skin/zen-icons/library/library-history-sprite.svg");
|
||||
}
|
||||
|
||||
[data-section="downloads"] :is(.zen-library-tab-icon-image, .empty-state-icon-image) {
|
||||
background-image: url("chrome://browser/skin/zen-icons/library/library-downloads-sprite.svg");
|
||||
}
|
||||
|
||||
[data-section="boosts"] :is(.zen-library-tab-icon-image, .empty-state-icon-image) {
|
||||
background-image: url("chrome://browser/skin/zen-icons/library/library-boosts-sprite.svg");
|
||||
}
|
||||
|
||||
[data-section="spaces"] :is(.zen-library-tab-icon-image, .empty-state-icon-image) {
|
||||
background-image: url("chrome://browser/skin/zen-icons/library/library-spaces-sprite.svg");
|
||||
}
|
||||
|
||||
[data-section="media"] :is(.zen-library-tab-icon-image, .empty-state-icon-image) {
|
||||
background-image: url("chrome://browser/skin/zen-icons/library/library-media-sprite.svg");
|
||||
}
|
||||
|
||||
@keyframes zen-library-sprite-play {
|
||||
from {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translateX(calc(35 * -28px));
|
||||
transform: translateX(calc(35 * -1 * var(--zen-library-sprite-size)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,7 +365,7 @@ zen-library[open] {
|
||||
}
|
||||
|
||||
.library-item:hover .library-item-background {
|
||||
background-color: var(--tab-hover-background-color);
|
||||
background-color: var(--tab-background-color-hover);
|
||||
outline-color: var(--tab-hover-outline-color);
|
||||
}
|
||||
|
||||
@@ -573,11 +577,36 @@ zen-library[open] {
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
font-size: 2em;
|
||||
font-weight: 600;
|
||||
opacity: 0.5;
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
animation: zen-library-empty-state-enter 0.3s cubic-bezier(0.32, 0.72, 0, 1);
|
||||
|
||||
& .empty-state-icon-image {
|
||||
animation: zen-library-sprite-play 0.583s steps(36, jump-none);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zen-library-empty-state-enter {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(12px) scale(0.98);
|
||||
}
|
||||
}
|
||||
|
||||
.empty-state-icon {
|
||||
--zen-library-sprite-size: 56px;
|
||||
|
||||
width: var(--zen-library-sprite-size);
|
||||
height: var(--zen-library-sprite-size);
|
||||
overflow: clip;
|
||||
}
|
||||
|
||||
/* Boosts section */
|
||||
|
||||
Reference in New Issue
Block a user