mirror of
https://github.com/zen-browser/desktop.git
synced 2026-04-20 06:21:00 +00:00
feat: Animate glances comming from unknown sources, p=#10894, c=glance
* feat: Animate glances comming from unknown sources, b=no-bug, c=glance * chore: Fixed linter, b=no-bug, c=glance
This commit is contained in:
@@ -24,6 +24,9 @@
|
||||
#duringOpening = false;
|
||||
#ignoreClose = false;
|
||||
|
||||
// Click handling
|
||||
#lastLinkClickData = { clientX: 0, clientY: 0, height: 0, width: 0 };
|
||||
|
||||
// Arc animation configuration
|
||||
#ARC_CONFIG = Object.freeze({
|
||||
ARC_STEPS: 70, // Increased for smoother bounce
|
||||
@@ -268,10 +271,31 @@
|
||||
data.height
|
||||
);
|
||||
return await this.#imageBitmapToBase64(
|
||||
await window.browsingContext.currentWindowGlobal.drawSnapshot(rect, 1, 'transparent', true)
|
||||
await window.browsingContext.currentWindowGlobal.drawSnapshot(
|
||||
rect,
|
||||
1,
|
||||
'transparent',
|
||||
undefined
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the last link click data
|
||||
* @param {Object} data - The link click data
|
||||
*/
|
||||
set lastLinkClickData(data) {
|
||||
this.#lastLinkClickData = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last link click data
|
||||
* @returns {Object} The last link click data
|
||||
*/
|
||||
get lastLinkClickData() {
|
||||
return this.#lastLinkClickData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a glance overlay with the specified data
|
||||
* @param {Object} data - Glance data including URL, position, and dimensions
|
||||
@@ -289,6 +313,13 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data.height || !data.width) {
|
||||
data = {
|
||||
...data,
|
||||
...this.lastLinkClickData,
|
||||
};
|
||||
}
|
||||
|
||||
this.#setAnimationState(true);
|
||||
const currentTab = ownerTab ?? gBrowser.selectedTab;
|
||||
const browserElement = this.#createBrowserElement(data.url, currentTab, existingTab);
|
||||
@@ -325,6 +356,9 @@
|
||||
gZenViewSplitter.onLocationChange(browserElement);
|
||||
this.#prepareGlanceAnimation(data, browserElement);
|
||||
if (data.width && data.height) {
|
||||
// It is guaranteed that we will animate this opacity later on
|
||||
// when we start animating the glance.
|
||||
this.contentWrapper.style.opacity = 0;
|
||||
data.elementData = await this.#getElementPreviewData(data);
|
||||
}
|
||||
this.#glances.get(this.#currentGlanceID).elementData = data.elementData;
|
||||
@@ -342,7 +376,6 @@
|
||||
const newButtons = this.#createNewOverlayButtons();
|
||||
this.browserWrapper.appendChild(newButtons);
|
||||
|
||||
this.#animateParentBackground();
|
||||
this.#setupGlancePositioning(data);
|
||||
this.#configureBrowserElement(browserElement);
|
||||
}
|
||||
@@ -486,7 +519,6 @@
|
||||
// nice fade-in effect to the content. But if it doesn't exist,
|
||||
// we just fall back to always showing the browser directly.
|
||||
if (data.elementData) {
|
||||
this.contentWrapper.style.opacity = 0;
|
||||
gZenUIManager.motion
|
||||
.animate(
|
||||
this.contentWrapper,
|
||||
@@ -501,6 +533,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
this.#animateParentBackground();
|
||||
gZenUIManager.motion
|
||||
.animate(this.browserWrapper, arcSequence, {
|
||||
duration: gZenUIManager.testingEnabled ? 0 : 0.4,
|
||||
@@ -1355,22 +1388,9 @@
|
||||
* @param {Tab} tab - The tab to open glance for
|
||||
*/
|
||||
#openGlanceForTab(tab) {
|
||||
const browserRect = window.windowUtils.getBoundsWithoutFlushing(gBrowser.tabpanels);
|
||||
const clickPosition = gZenUIManager._lastClickPosition || {
|
||||
clientX: browserRect.width / 2,
|
||||
clientY: browserRect.height / 2,
|
||||
};
|
||||
|
||||
// Make it relative to the tabpanels
|
||||
clickPosition.clientX -= browserRect.left;
|
||||
clickPosition.clientY -= browserRect.top;
|
||||
|
||||
this.openGlance(
|
||||
{
|
||||
url: undefined,
|
||||
...clickPosition,
|
||||
width: 0,
|
||||
height: 0,
|
||||
},
|
||||
tab,
|
||||
tab.owner
|
||||
|
||||
@@ -35,22 +35,30 @@ export class ZenGlanceChild extends JSWindowActorChild {
|
||||
return !(event.ctrlKey ^ event.altKey ^ event.shiftKey ^ event.metaKey);
|
||||
}
|
||||
|
||||
openGlance(target, originalTarget) {
|
||||
#openGlance(target) {
|
||||
let url = target.href;
|
||||
// Add domain to relative URLs
|
||||
if (!url.match(/^(?:[a-z]+:)?\/\//i)) {
|
||||
url = this.contentWindow.location.origin + url;
|
||||
}
|
||||
this.sendAsyncMessage('ZenGlance:OpenGlance', {
|
||||
url,
|
||||
});
|
||||
}
|
||||
|
||||
#sendClickDataToParent(target, element) {
|
||||
if (!element || !target) {
|
||||
return;
|
||||
}
|
||||
// Get the largest element we can get. If the `A` element
|
||||
// is a parent of the original target, use the anchor element,
|
||||
// otherwise use the original target.
|
||||
let rect = originalTarget.getBoundingClientRect();
|
||||
let rect = element.getBoundingClientRect();
|
||||
const anchorRect = target.getBoundingClientRect();
|
||||
if (anchorRect.width * anchorRect.height > rect.width * rect.height) {
|
||||
rect = anchorRect;
|
||||
}
|
||||
this.sendAsyncMessage('ZenGlance:OpenGlance', {
|
||||
url,
|
||||
this.sendAsyncMessage('ZenGlance:RecordLinkClickData', {
|
||||
clientX: rect.left,
|
||||
clientY: rect.top,
|
||||
width: rect.width,
|
||||
@@ -59,7 +67,19 @@ export class ZenGlanceChild extends JSWindowActorChild {
|
||||
}
|
||||
|
||||
handleClick(event) {
|
||||
if (this.ensureOnlyKeyModifiers(event) || event.button !== 0 || event.defaultPrevented) {
|
||||
if (event.button !== 0 || event.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
// get closest A element
|
||||
const target = event.target.closest('A');
|
||||
const elementToRecord = event.originalTarget || event.target;
|
||||
// We record the link data anyway, even if the glance may be invoked
|
||||
// or not. We have some cases where glance would open, for example,
|
||||
// when clicking on a link with a different domain where glance would open.
|
||||
// The problem is that at that stage we don't know the rect or even what
|
||||
// element has been clicked, so we send the data here.
|
||||
this.#sendClickDataToParent(target, elementToRecord);
|
||||
if (this.ensureOnlyKeyModifiers(event)) {
|
||||
return;
|
||||
}
|
||||
const activationMethod = this.#activationMethod;
|
||||
@@ -72,13 +92,11 @@ export class ZenGlanceChild extends JSWindowActorChild {
|
||||
} else if (activationMethod === 'meta' && !event.metaKey) {
|
||||
return;
|
||||
}
|
||||
// get closest A element
|
||||
const target = event.target.closest('A');
|
||||
if (target) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
this.openGlance(target, event.originalTarget || event.target);
|
||||
this.#openGlance(target);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,10 @@ export class ZenGlanceParent extends JSWindowActorParent {
|
||||
this.browsingContext.topChromeWindow.gZenGlanceManager.closeGlance(params);
|
||||
break;
|
||||
}
|
||||
case 'ZenGlance:RecordLinkClickData': {
|
||||
this.browsingContext.topChromeWindow.gZenGlanceManager.lastLinkClickData = message.data;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
console.warn(`[glance]: Unknown message: ${message.name}`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user