mirror of
https://github.com/zen-browser/desktop.git
synced 2026-07-12 20:00:29 +00:00
Compare commits
1 Commits
1.19b
...
chore/6198
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dee1d2c279 |
@@ -35,7 +35,7 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
|||||||
ARC_HEIGHT_RATIO: 0.2, // Arc height = distance * ratio (capped at MAX_ARC_HEIGHT)
|
ARC_HEIGHT_RATIO: 0.2, // Arc height = distance * ratio (capped at MAX_ARC_HEIGHT)
|
||||||
});
|
});
|
||||||
|
|
||||||
#GLANCE_ANIMATION_DURATION = Services.prefs.getIntPref('zen.glance.animation-duration') / 1000;
|
#GLANCE_ANIMATION_DURATION = Services.prefs.getIntPref('zen.glance.animation-duration');
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this.#setupEventListeners();
|
this.#setupEventListeners();
|
||||||
@@ -253,19 +253,21 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
|||||||
|
|
||||||
const xOffset = gZenVerticalTabsManager._prefsRightSide ? 20 : -20;
|
const xOffset = gZenVerticalTabsManager._prefsRightSide ? 20 : -20;
|
||||||
|
|
||||||
gZenUIManager.motion.animate(
|
setTimeout(() => {
|
||||||
container,
|
gZenUIManager.elementAnimate(
|
||||||
{
|
container,
|
||||||
opacity: [0, 1],
|
{
|
||||||
x: [xOffset, 0],
|
opacity: [0, 1],
|
||||||
},
|
x: [xOffset, 0],
|
||||||
{
|
},
|
||||||
duration: 0.2,
|
{
|
||||||
type: 'spring',
|
duration: 200,
|
||||||
delay: this.#GLANCE_ANIMATION_DURATION - 0.2,
|
easing: 'ease-in-out',
|
||||||
bounce: 0,
|
fill: 'forwards',
|
||||||
}
|
delay: this.#GLANCE_ANIMATION_DURATION - 200,
|
||||||
);
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -403,7 +405,7 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
|||||||
'.browserSidebarContainer'
|
'.browserSidebarContainer'
|
||||||
);
|
);
|
||||||
|
|
||||||
gZenUIManager.motion.animate(
|
gZenUIManager.elementAnimate(
|
||||||
parentSidebarContainer,
|
parentSidebarContainer,
|
||||||
{
|
{
|
||||||
scale: [1, 0.98],
|
scale: [1, 0.98],
|
||||||
@@ -411,8 +413,8 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
duration: this.#GLANCE_ANIMATION_DURATION,
|
duration: this.#GLANCE_ANIMATION_DURATION,
|
||||||
type: 'spring',
|
easing: 'ease-in-out',
|
||||||
bounce: 0.2,
|
fill: 'forwards',
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -428,8 +430,7 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
|||||||
|
|
||||||
this.overlay.removeAttribute('fade-out');
|
this.overlay.removeAttribute('fade-out');
|
||||||
this.browserWrapper.setAttribute('animate', true);
|
this.browserWrapper.setAttribute('animate', true);
|
||||||
this.browserWrapper.style.top = `${top}px`;
|
this.browserWrapper.style.transform = `translate(${left}px, ${top}px)`;
|
||||||
this.browserWrapper.style.left = `${left}px`;
|
|
||||||
this.browserWrapper.style.width = `${width}px`;
|
this.browserWrapper.style.width = `${width}px`;
|
||||||
this.browserWrapper.style.height = `${height}px`;
|
this.browserWrapper.style.height = `${height}px`;
|
||||||
|
|
||||||
@@ -441,9 +442,18 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
|||||||
* Store the original position for later restoration
|
* Store the original position for later restoration
|
||||||
*/
|
*/
|
||||||
#storeOriginalPosition() {
|
#storeOriginalPosition() {
|
||||||
|
let transform = this.browserWrapper.style.transform;
|
||||||
|
let [top, left] = [0, 0];
|
||||||
|
if (transform && transform.startsWith('translate(')) {
|
||||||
|
const match = transform.match(/translate\(([-\d.]+)px,\s*([-\d.]+)px\)/);
|
||||||
|
if (match) {
|
||||||
|
left = parseFloat(match[1]);
|
||||||
|
top = parseFloat(match[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
this.#glances.get(this.#currentGlanceID).originalPosition = {
|
this.#glances.get(this.#currentGlanceID).originalPosition = {
|
||||||
top: this.browserWrapper.style.top,
|
top,
|
||||||
left: this.browserWrapper.style.left,
|
left,
|
||||||
width: this.browserWrapper.style.width,
|
width: this.browserWrapper.style.width,
|
||||||
height: this.browserWrapper.style.height,
|
height: this.browserWrapper.style.height,
|
||||||
};
|
};
|
||||||
@@ -473,14 +483,14 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
|||||||
this.browserWrapper.prepend(imageDataElement);
|
this.browserWrapper.prepend(imageDataElement);
|
||||||
this.#glances.get(this.#currentGlanceID).elementImageData = data.elementData;
|
this.#glances.get(this.#currentGlanceID).elementImageData = data.elementData;
|
||||||
|
|
||||||
gZenUIManager.motion.animate(
|
gZenUIManager.elementAnimate(
|
||||||
imageDataElement,
|
imageDataElement,
|
||||||
{
|
{
|
||||||
opacity: [1, 0],
|
opacity: [1, 0],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
duration: this.#GLANCE_ANIMATION_DURATION / 2,
|
duration: this.#GLANCE_ANIMATION_DURATION / 2,
|
||||||
easing: 'easeInOut',
|
easing: 'ease-in-out',
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -500,16 +510,6 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
|||||||
browserElement.style.minHeight = `${minHeight}px`;
|
browserElement.style.minHeight = `${minHeight}px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the transform origin for the animation
|
|
||||||
* @param {Object} data - Glance data with position and dimensions
|
|
||||||
* @returns {string} The transform origin CSS value
|
|
||||||
*/
|
|
||||||
#getTransformOrigin(data) {
|
|
||||||
const { clientX, clientY } = data;
|
|
||||||
return `${clientX}px ${clientY}px`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the main glance animation
|
* Execute the main glance animation
|
||||||
* @param {Object} data - Glance data
|
* @param {Object} data - Glance data
|
||||||
@@ -521,21 +521,18 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
|||||||
|
|
||||||
// Create curved animation sequence
|
// Create curved animation sequence
|
||||||
const arcSequence = this.#createGlanceArcSequence(data, 'opening');
|
const arcSequence = this.#createGlanceArcSequence(data, 'opening');
|
||||||
const transformOrigin = this.#getTransformOrigin(data);
|
|
||||||
|
|
||||||
this.browserWrapper.style.transformOrigin = transformOrigin;
|
|
||||||
|
|
||||||
// Only animate if there is element data, so we can apply a
|
// Only animate if there is element data, so we can apply a
|
||||||
// nice fade-in effect to the content. But if it doesn't exist,
|
// nice fade-in effect to the content. But if it doesn't exist,
|
||||||
// we just fall back to always showing the browser directly.
|
// we just fall back to always showing the browser directly.
|
||||||
if (data.elementData) {
|
if (data.elementData) {
|
||||||
gZenUIManager.motion
|
gZenUIManager
|
||||||
.animate(
|
.elementAnimate(
|
||||||
this.contentWrapper,
|
this.contentWrapper,
|
||||||
{ opacity: [0, 1] },
|
{ opacity: [0, 1] },
|
||||||
{
|
{
|
||||||
duration: this.#GLANCE_ANIMATION_DURATION / 2,
|
duration: this.#GLANCE_ANIMATION_DURATION / 2,
|
||||||
easing: 'easeInOut',
|
easing: 'ease-in-out',
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -544,10 +541,9 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.#animateParentBackground();
|
this.#animateParentBackground();
|
||||||
gZenUIManager.motion
|
gZenUIManager
|
||||||
.animate(this.browserWrapper, arcSequence, {
|
.elementAnimate(this.browserWrapper, arcSequence, {
|
||||||
duration: gZenUIManager.testingEnabled ? 0 : this.#GLANCE_ANIMATION_DURATION,
|
duration: gZenUIManager.testingEnabled ? 0 : this.#GLANCE_ANIMATION_DURATION,
|
||||||
ease: 'easeInOut',
|
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.#finalizeGlanceOpening(imageDataElement, browserElement, resolve);
|
this.#finalizeGlanceOpening(imageDataElement, browserElement, resolve);
|
||||||
@@ -607,28 +603,29 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const sequence = {
|
const sequence = {
|
||||||
top: [],
|
transform: [],
|
||||||
left: [],
|
|
||||||
width: [],
|
width: [],
|
||||||
height: [],
|
height: [],
|
||||||
transform: [],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const steps = this.#ARC_CONFIG.ARC_STEPS;
|
const steps = this.#ARC_CONFIG.ARC_STEPS;
|
||||||
const arcDirection = shouldArcDownward ? 1 : -1;
|
const arcDirection = shouldArcDownward ? 1 : -1;
|
||||||
|
|
||||||
function easeInOutQuad(t) {
|
function easeOutBack(x) {
|
||||||
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
|
const c1 = 0.4;
|
||||||
|
const c3 = c1 + 1;
|
||||||
|
|
||||||
|
return 1 + c3 * (x - 1) ** 3 + c1 * (x - 1) ** 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
function easeOutCubic(t) {
|
function easeInQuint(x) {
|
||||||
return 1 - Math.pow(1 - t, 6);
|
return x * x * x * x * x;
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, create the main animation steps
|
// First, create the main animation steps
|
||||||
for (let i = 0; i <= steps; i++) {
|
for (let i = 0; i <= steps; i++) {
|
||||||
const progress = i / steps;
|
const progress = i / steps;
|
||||||
const eased = direction === 'opening' ? easeInOutQuad(progress) : easeOutCubic(progress);
|
const eased = direction === 'opening' ? easeOutBack(progress) : easeInQuint(progress);
|
||||||
|
|
||||||
// Calculate size interpolation
|
// Calculate size interpolation
|
||||||
const currentWidth = startPosition.width + (endPosition.width - startPosition.width) * eased;
|
const currentWidth = startPosition.width + (endPosition.width - startPosition.width) * eased;
|
||||||
@@ -643,32 +640,11 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
|||||||
const y =
|
const y =
|
||||||
startPosition.y + distanceY * eased + arcDirection * arcHeight * (1 - (2 * eased - 1) ** 2);
|
startPosition.y + distanceY * eased + arcDirection * arcHeight * (1 - (2 * eased - 1) ** 2);
|
||||||
|
|
||||||
sequence.transform.push(`translate(-50%, -50%) scale(1)`);
|
sequence.transform.push(`translate(${x}px, ${y}px)`);
|
||||||
sequence.top.push(`${y}px`);
|
|
||||||
sequence.left.push(`${x}px`);
|
|
||||||
sequence.width.push(`${currentWidth}px`);
|
sequence.width.push(`${currentWidth}px`);
|
||||||
sequence.height.push(`${currentHeight}px`);
|
sequence.height.push(`${currentHeight}px`);
|
||||||
}
|
}
|
||||||
|
|
||||||
let scale = 1;
|
|
||||||
const bounceSteps = 60;
|
|
||||||
if (direction === 'opening') {
|
|
||||||
for (let i = 0; i < bounceSteps; i++) {
|
|
||||||
const progress = i / bounceSteps;
|
|
||||||
// Scale up slightly then back to normal
|
|
||||||
scale = 1 + 0.003 * Math.sin(progress * Math.PI);
|
|
||||||
// If we are at the last step, ensure scale is exactly 1
|
|
||||||
if (i === bounceSteps - 1) {
|
|
||||||
scale = 1;
|
|
||||||
}
|
|
||||||
sequence.transform.push(`translate(-50%, -50%) scale(${scale})`);
|
|
||||||
sequence.top.push(sequence.top[sequence.top.length - 1]);
|
|
||||||
sequence.left.push(sequence.left[sequence.left.length - 1]);
|
|
||||||
sequence.width.push(sequence.width[sequence.width.length - 1]);
|
|
||||||
sequence.height.push(sequence.height[sequence.height.length - 1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sequence;
|
return sequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -724,8 +700,6 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
|||||||
imageDataElement.remove();
|
imageDataElement.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.browserWrapper.style.transformOrigin = '';
|
|
||||||
|
|
||||||
browserElement.style.minWidth = '';
|
browserElement.style.minWidth = '';
|
||||||
browserElement.style.minHeight = '';
|
browserElement.style.minHeight = '';
|
||||||
|
|
||||||
@@ -892,14 +866,14 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
|||||||
*/
|
*/
|
||||||
#animateSidebarButtons(sidebarButtons) {
|
#animateSidebarButtons(sidebarButtons) {
|
||||||
if (sidebarButtons) {
|
if (sidebarButtons) {
|
||||||
gZenUIManager.motion
|
gZenUIManager
|
||||||
.animate(
|
.elementAnimate(
|
||||||
sidebarButtons,
|
sidebarButtons,
|
||||||
{ opacity: [1, 0] },
|
{ opacity: [1, 0] },
|
||||||
{
|
{
|
||||||
duration: 0.2,
|
duration: 100,
|
||||||
type: 'spring',
|
easing: 'ease-in-out',
|
||||||
bounce: this.#GLANCE_ANIMATION_DURATION - 0.1,
|
fill: 'forwards',
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -928,8 +902,8 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
|||||||
* @param {Element} browserSidebarContainer - The sidebar container
|
* @param {Element} browserSidebarContainer - The sidebar container
|
||||||
*/
|
*/
|
||||||
#animateParentBackgroundClose(browserSidebarContainer) {
|
#animateParentBackgroundClose(browserSidebarContainer) {
|
||||||
gZenUIManager.motion
|
gZenUIManager
|
||||||
.animate(
|
.elementAnimate(
|
||||||
browserSidebarContainer,
|
browserSidebarContainer,
|
||||||
{
|
{
|
||||||
scale: [0.98, 1],
|
scale: [0.98, 1],
|
||||||
@@ -937,8 +911,7 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
duration: this.#GLANCE_ANIMATION_DURATION / 1.5,
|
duration: this.#GLANCE_ANIMATION_DURATION / 1.5,
|
||||||
type: 'spring',
|
easing: 'ease-in-out',
|
||||||
bounce: 0,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -965,10 +938,9 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
|||||||
const closingData = this.#createClosingDataFromOriginalPosition(originalPosition);
|
const closingData = this.#createClosingDataFromOriginalPosition(originalPosition);
|
||||||
const arcSequence = this.#createGlanceArcSequence(closingData, 'closing');
|
const arcSequence = this.#createGlanceArcSequence(closingData, 'closing');
|
||||||
|
|
||||||
gZenUIManager.motion
|
gZenUIManager
|
||||||
.animate(this.browserWrapper, arcSequence, {
|
.elementAnimate(this.browserWrapper, arcSequence, {
|
||||||
duration: this.#GLANCE_ANIMATION_DURATION,
|
duration: this.#GLANCE_ANIMATION_DURATION,
|
||||||
ease: 'easeOut',
|
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Remove element preview after closing animation
|
// Remove element preview after closing animation
|
||||||
@@ -1485,7 +1457,7 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
|||||||
this.browserWrapper.style.width = `${browserRect.width}px`;
|
this.browserWrapper.style.width = `${browserRect.width}px`;
|
||||||
this.browserWrapper.style.height = `${browserRect.height}px`;
|
this.browserWrapper.style.height = `${browserRect.height}px`;
|
||||||
|
|
||||||
await gZenUIManager.motion.animate(
|
await gZenUIManager.elementAnimate(
|
||||||
this.browserWrapper,
|
this.browserWrapper,
|
||||||
{
|
{
|
||||||
width: ['85%', '100%'],
|
width: ['85%', '100%'],
|
||||||
@@ -1493,8 +1465,7 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
duration: this.#GLANCE_ANIMATION_DURATION,
|
duration: this.#GLANCE_ANIMATION_DURATION,
|
||||||
type: 'spring',
|
easing: 'ease-in-out',
|
||||||
bounce: 0,
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -125,7 +125,7 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
flex: unset !important;
|
flex: unset !important;
|
||||||
/* Promote to its own layer during transitions to reduce jank */
|
/* Promote to its own layer during transitions to reduce jank */
|
||||||
will-change: transform, top, left;
|
will-change: transform;
|
||||||
width: 85%;
|
width: 85%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
@@ -148,6 +148,10 @@
|
|||||||
box-shadow: var(--zen-big-shadow);
|
box-shadow: var(--zen-big-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:not([has-finished-animation='true']) .browserStack {
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
& browser {
|
& browser {
|
||||||
background: light-dark(rgb(255, 255, 255), rgb(32, 32, 32)) !important;
|
background: light-dark(rgb(255, 255, 255), rgb(32, 32, 32)) !important;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
Reference in New Issue
Block a user