mirror of
https://github.com/zen-browser/desktop.git
synced 2025-09-05 19:08:18 +00:00
feat(glance): glance buttons fix overflow
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
<vbox id="zen-glance-sidebar-container" hidden="true">
|
||||
<toolbarbutton id="zen-glance-sidebar-close" class="toolbarbutton-1" oncommand="gZenGlanceManager.closeGlance({ onTabClose: true })"/>
|
||||
<toolbarbutton id="zen-glance-sidebar-open" class="toolbarbutton-1" oncommand="gZenGlanceManager.fullyOpenGlance()"/>
|
||||
<vbox id="glance-wrapper" style="position: relative; overflow: visible;">
|
||||
<vbox id="zen-glance-sidebar-container" hidden="true">
|
||||
<toolbarbutton id="zen-glance-sidebar-close" class="toolbarbutton-1" oncommand="gZenGlanceManager.closeGlance({ onTabClose: true })"/>
|
||||
<toolbarbutton id="zen-glance-sidebar-open" class="toolbarbutton-1" oncommand="gZenGlanceManager.fullyOpenGlance()"/>
|
||||
</vbox>
|
||||
</vbox>
|
||||
|
@@ -9,6 +9,12 @@
|
||||
visibility: inherit;
|
||||
}
|
||||
|
||||
#glance-wrapper {
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
left: 2%;
|
||||
}
|
||||
|
||||
#zen-glance-sidebar-container {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
@@ -23,7 +29,6 @@
|
||||
|
||||
padding: 5px;
|
||||
gap: 12px;
|
||||
left: 2%;
|
||||
|
||||
& toolbarbutton {
|
||||
width: 32px;
|
||||
@@ -49,6 +54,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
#zen-glance-sidebar-container[hidden='true'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.browserSidebarContainer.zen-glance-overlay {
|
||||
box-shadow: none !important;
|
||||
|
||||
|
@@ -11,36 +11,31 @@
|
||||
window.addEventListener('TabClose', this.onTabClose.bind(this));
|
||||
window.addEventListener('TabSelect', this.onLocationChange.bind(this));
|
||||
|
||||
ChromeUtils.defineLazyGetter(this, 'sidebarButtons', () => document.getElementById('zen-glance-sidebar-container'));
|
||||
document.getElementById('tabbrowser-tabpanels').addEventListener('click', this.onOverlayClick.bind(this));
|
||||
Services.obs.addObserver(this, 'quit-application-requested');
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this._lazyPref,
|
||||
'SHOULD_OPEN_EXTERNAL_TABS_IN_GLANCE',
|
||||
'zen.glance.open-essential-external-links',
|
||||
false
|
||||
);
|
||||
|
||||
ChromeUtils.defineLazyGetter(this, 'sidebarButtons', () => document.getElementById('zen-glance-sidebar-container'));
|
||||
|
||||
document.getElementById('tabbrowser-tabpanels').addEventListener('click', this.onOverlayClick.bind(this));
|
||||
|
||||
Services.obs.addObserver(this, 'quit-application-requested');
|
||||
}
|
||||
|
||||
get #currentBrowser() {
|
||||
return this.#glances.get(this.#currentGlanceID)?.browser;
|
||||
}
|
||||
|
||||
get #currentTab() {
|
||||
return this.#glances.get(this.#currentGlanceID)?.tab;
|
||||
}
|
||||
|
||||
get #currentParentTab() {
|
||||
return this.#glances.get(this.#currentGlanceID)?.parentTab;
|
||||
}
|
||||
|
||||
// If the user presses Escape while a Glance is open, close it
|
||||
onKeyDown(event) {
|
||||
if (event.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
if (event.defaultPrevented) return;
|
||||
if (event.key === 'Escape' && this.#currentGlanceID) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
@@ -49,6 +44,7 @@
|
||||
}
|
||||
|
||||
onOverlayClick(event) {
|
||||
// If user clicks outside content area, close glance
|
||||
if (event.target === this.overlay && event.originalTarget !== this.contentWrapper) {
|
||||
this.closeGlance({ onTabClose: true });
|
||||
}
|
||||
@@ -63,16 +59,18 @@
|
||||
}
|
||||
|
||||
onUnload() {
|
||||
// clear everything
|
||||
// Clean up all open Glances
|
||||
for (let [id, glance] of this.#glances) {
|
||||
gBrowser.removeTab(glance.tab, { animate: false });
|
||||
}
|
||||
}
|
||||
|
||||
// Figure out where to insert new tabs
|
||||
getTabPosition(tab) {
|
||||
return Math.max(gBrowser._numVisiblePinTabs, tab._tPos);
|
||||
}
|
||||
|
||||
// Create a new tab for Glance
|
||||
createBrowserElement(url, currentTab, existingTab = null) {
|
||||
const newTabOptions = {
|
||||
userContextId: currentTab.getAttribute('usercontextid') || '',
|
||||
@@ -82,15 +80,21 @@
|
||||
index: this.getTabPosition(currentTab),
|
||||
};
|
||||
currentTab._selected = true;
|
||||
|
||||
const newUUID = gZenUIManager.generateUuidv4();
|
||||
const newTab = existingTab ?? gBrowser.addTrustedTab(Services.io.newURI(url).spec, newTabOptions);
|
||||
|
||||
// Example: copy any context ID
|
||||
if (currentTab.hasAttribute('zenDefaultUserContextId')) {
|
||||
newTab.setAttribute('zenDefaultUserContextId', true);
|
||||
}
|
||||
|
||||
// Insert the new tab as a child of the existing tab's content
|
||||
currentTab.querySelector('.tab-content').appendChild(newTab);
|
||||
newTab.setAttribute('zen-glance-tab', true);
|
||||
newTab.setAttribute('glance-id', newUUID);
|
||||
currentTab.setAttribute('glance-id', newUUID);
|
||||
|
||||
this.#glances.set(newUUID, {
|
||||
tab: newTab,
|
||||
parentTab: currentTab,
|
||||
@@ -102,12 +106,14 @@
|
||||
}
|
||||
|
||||
fillOverlay(browser) {
|
||||
// Save references to the parent containers
|
||||
this.overlay = browser.closest('.browserSidebarContainer');
|
||||
this.browserWrapper = browser.closest('.browserContainer');
|
||||
this.contentWrapper = browser.closest('.browserStack');
|
||||
}
|
||||
|
||||
showSidebarButtons(animate = false) {
|
||||
// Animate in if hidden
|
||||
if (this.sidebarButtons.hasAttribute('hidden') && animate) {
|
||||
gZenUIManager.motion.animate(
|
||||
this.sidebarButtons.querySelectorAll('toolbarbutton'),
|
||||
@@ -123,40 +129,57 @@
|
||||
}
|
||||
|
||||
openGlance(data, existingTab = null, ownerTab = null) {
|
||||
// If a glance is already open, do nothing
|
||||
if (this.#currentBrowser) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the current parent tab is selected, switch to the glance tab
|
||||
if (gBrowser.selectedTab === this.#currentParentTab) {
|
||||
gBrowser.selectedTab = this.#currentTab;
|
||||
return;
|
||||
}
|
||||
|
||||
this.animatingOpen = true;
|
||||
this._animating = true;
|
||||
|
||||
// Gather initial positions
|
||||
const initialX = data.x;
|
||||
const initialY = data.y;
|
||||
const initialWidth = data.width;
|
||||
const initialHeight = data.height;
|
||||
|
||||
// Clean up any leftover states
|
||||
this.browserWrapper?.removeAttribute('animate');
|
||||
this.browserWrapper?.removeAttribute('animate-end');
|
||||
this.browserWrapper?.removeAttribute('animate-full');
|
||||
this.browserWrapper?.removeAttribute('has-finished-animation');
|
||||
this.overlay?.removeAttribute('post-fade-out');
|
||||
|
||||
// Create the new tab
|
||||
const currentTab = ownerTab ?? gBrowser.selectedTab;
|
||||
|
||||
const browserElement = this.createBrowserElement(data.url, currentTab, existingTab);
|
||||
|
||||
// Fill references
|
||||
this.fillOverlay(browserElement);
|
||||
|
||||
const container = document.getElementById('glance-wrapper');
|
||||
if (container) {
|
||||
container.appendChild(this.sidebarButtons);
|
||||
}
|
||||
|
||||
// Start overlay
|
||||
this.overlay.classList.add('zen-glance-overlay');
|
||||
|
||||
// Animate open
|
||||
this.browserWrapper.removeAttribute('animate-end');
|
||||
window.requestAnimationFrame(() => {
|
||||
// "Quick open" logic
|
||||
this.quickOpenGlance({ dontOpenButtons: true });
|
||||
// Show the sidebar buttons
|
||||
this.showSidebarButtons(true);
|
||||
|
||||
// Animate the parent container
|
||||
gZenUIManager.motion.animate(
|
||||
this.#currentParentTab.linkedBrowser.closest('.browserSidebarContainer'),
|
||||
{
|
||||
@@ -170,9 +193,12 @@
|
||||
bounce: 0.2,
|
||||
}
|
||||
);
|
||||
|
||||
// Start the transition
|
||||
this.#currentBrowser.setAttribute('animate-glance-open', true);
|
||||
this.overlay.removeAttribute('fade-out');
|
||||
this.browserWrapper.setAttribute('animate', true);
|
||||
|
||||
const top = initialY + initialHeight / 2;
|
||||
const left = initialX + initialWidth / 2;
|
||||
this.browserWrapper.style.top = `${top}px`;
|
||||
@@ -180,14 +206,19 @@
|
||||
this.browserWrapper.style.width = `${initialWidth}px`;
|
||||
this.browserWrapper.style.height = `${initialHeight}px`;
|
||||
this.browserWrapper.style.opacity = 0.8;
|
||||
|
||||
// Save original position for closing animation
|
||||
this.#glances.get(this.#currentGlanceID).originalPosition = {
|
||||
top: this.browserWrapper.style.top,
|
||||
left: this.browserWrapper.style.left,
|
||||
width: this.browserWrapper.style.width,
|
||||
height: this.browserWrapper.style.height,
|
||||
};
|
||||
|
||||
this.browserWrapper.style.transform = 'translate(-50%, -50%)';
|
||||
this.overlay.style.overflow = 'visible';
|
||||
|
||||
// Animate up to final size
|
||||
gZenUIManager.motion
|
||||
.animate(
|
||||
this.browserWrapper,
|
||||
@@ -231,24 +262,26 @@
|
||||
this.closingGlance = true;
|
||||
this._animating = true;
|
||||
|
||||
// Insert tab at correct index
|
||||
gBrowser._insertTabAtIndex(this.#currentTab, {
|
||||
index: this.getTabPosition(this.#currentParentTab),
|
||||
});
|
||||
|
||||
let quikcCloseZen = false;
|
||||
if (onTabClose) {
|
||||
// Create new tab if no more ex
|
||||
// If there's only one tab left, open a new one
|
||||
if (gBrowser.tabs.length === 1) {
|
||||
BrowserCommands.openTab();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// do NOT touch here, I don't know what it does, but it works...
|
||||
// do NOT touch here, unknown but functional
|
||||
this.#currentTab.style.display = 'none';
|
||||
this.overlay.setAttribute('fade-out', true);
|
||||
this.overlay.style.pointerEvents = 'none';
|
||||
this.quickCloseGlance({ justAnimateParent: true, clearID: false });
|
||||
|
||||
// Animate the parent container
|
||||
const originalPosition = this.#glances.get(this.#currentGlanceID).originalPosition;
|
||||
gZenUIManager.motion
|
||||
.animate(
|
||||
@@ -267,6 +300,8 @@
|
||||
.then(() => {
|
||||
this.#currentParentTab.linkedBrowser.closest('.browserSidebarContainer').removeAttribute('style');
|
||||
});
|
||||
|
||||
// Animate the browser wrapper back
|
||||
gZenUIManager.motion
|
||||
.animate(
|
||||
this.browserWrapper,
|
||||
@@ -283,9 +318,8 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if (!onTabClose || quikcCloseZen) {
|
||||
this.quickCloseGlance({ clearID: false });
|
||||
}
|
||||
// Final close
|
||||
this.quickCloseGlance({ clearID: false });
|
||||
this.overlay.removeAttribute('fade-out');
|
||||
this.browserWrapper.removeAttribute('animate');
|
||||
|
||||
@@ -298,7 +332,7 @@
|
||||
this.#currentParentTab._visuallySelected = false;
|
||||
}
|
||||
|
||||
// reset everything
|
||||
// Reset everything
|
||||
const prevOverlay = this.overlay;
|
||||
this.browserWrapper = null;
|
||||
this.overlay = null;
|
||||
@@ -325,6 +359,10 @@
|
||||
this._animating = false;
|
||||
this.closingGlance = false;
|
||||
|
||||
// Hide the buttons globally whenever we close
|
||||
this.hideSidebarButtons();
|
||||
|
||||
// If we had another Glance queued, open it
|
||||
if (this.#currentGlanceID) {
|
||||
this.quickOpenGlance();
|
||||
}
|
||||
@@ -344,6 +382,7 @@
|
||||
parentBrowserContainer.classList.add('zen-glance-background');
|
||||
parentBrowserContainer.classList.remove('zen-glance-overlay');
|
||||
parentBrowserContainer.classList.add('deck-selected');
|
||||
|
||||
this.#currentParentTab.linkedBrowser.zenModeActive = true;
|
||||
this.#currentParentTab.linkedBrowser.docShellIsActive = true;
|
||||
this.#currentBrowser.zenModeActive = true;
|
||||
@@ -360,7 +399,6 @@
|
||||
|
||||
quickCloseGlance({ closeCurrentTab = true, closeParentTab = true, justAnimateParent = false, clearID = true } = {}) {
|
||||
const parentHasBrowser = !!this.#currentParentTab.linkedBrowser;
|
||||
this.hideSidebarButtons();
|
||||
if (parentHasBrowser) {
|
||||
this.#currentParentTab.linkedBrowser.closest('.browserSidebarContainer').classList.remove('zen-glance-background');
|
||||
}
|
||||
@@ -397,7 +435,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
// note: must be async to avoid timing issues
|
||||
// If location changes to a tab with a different glance-id, close the old one
|
||||
onLocationChange(event) {
|
||||
const tab = event.target;
|
||||
if (this.animatingFullOpen || this.closingGlance) {
|
||||
@@ -440,7 +478,6 @@
|
||||
return false;
|
||||
}
|
||||
this.closeGlance({ onTabClose: true, setNewID: isDifferent ? oldGlanceID : null, isDifferent });
|
||||
// only keep continueing tab close if we are not on the currently selected tab
|
||||
return !isDifferent;
|
||||
}
|
||||
return false;
|
||||
@@ -448,13 +485,9 @@
|
||||
|
||||
tabDomainsDiffer(tab1, url2) {
|
||||
try {
|
||||
if (!tab1) {
|
||||
return true;
|
||||
}
|
||||
if (!tab1) return true;
|
||||
let url1 = tab1.linkedBrowser.currentURI.spec;
|
||||
if (url1.startsWith('about:')) {
|
||||
return true;
|
||||
}
|
||||
if (url1.startsWith('about:')) return true;
|
||||
return Services.io.newURI(url1).host !== url2.host;
|
||||
} catch (e) {
|
||||
return true;
|
||||
@@ -476,9 +509,7 @@
|
||||
|
||||
onTabOpen(browser, uri) {
|
||||
let tab = gBrowser.getTabForBrowser(browser);
|
||||
if (!tab) {
|
||||
return;
|
||||
}
|
||||
if (!tab) return;
|
||||
try {
|
||||
if (this.shouldOpenTabInGlance(tab, uri)) {
|
||||
const browserRect = gBrowser.tabbox.getBoundingClientRect();
|
||||
@@ -512,9 +543,11 @@
|
||||
this.#currentTab.removeAttribute('glance-id');
|
||||
this.#currentParentTab.removeAttribute('glance-id');
|
||||
gBrowser.selectedTab = this.#currentTab;
|
||||
|
||||
this.#currentParentTab.linkedBrowser.closest('.browserSidebarContainer').classList.remove('zen-glance-background');
|
||||
this.#currentParentTab._visuallySelected = false;
|
||||
this.hideSidebarButtons();
|
||||
|
||||
if (gReduceMotion) {
|
||||
this.finishOpeningGlance();
|
||||
return;
|
||||
@@ -535,18 +568,11 @@
|
||||
|
||||
openGlanceForBookmark(event) {
|
||||
const activationMethod = Services.prefs.getStringPref('zen.glance.activation-method', 'ctrl');
|
||||
|
||||
if (activationMethod === 'ctrl' && !event.ctrlKey) {
|
||||
return;
|
||||
} else if (activationMethod === 'alt' && !event.altKey) {
|
||||
return;
|
||||
} else if (activationMethod === 'shift' && !event.shiftKey) {
|
||||
return;
|
||||
} else if (activationMethod === 'meta' && !event.metaKey) {
|
||||
return;
|
||||
} else if (activationMethod === 'mantain' || typeof activationMethod === 'undefined') {
|
||||
return;
|
||||
}
|
||||
if (activationMethod === 'ctrl' && !event.ctrlKey) return;
|
||||
if (activationMethod === 'alt' && !event.altKey) return;
|
||||
if (activationMethod === 'shift' && !event.shiftKey) return;
|
||||
if (activationMethod === 'meta' && !event.metaKey) return;
|
||||
if (activationMethod === 'mantain' || typeof activationMethod === 'undefined') return;
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
@@ -559,9 +585,7 @@
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
};
|
||||
|
||||
this.openGlance(data);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -570,8 +594,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Expose globally
|
||||
window.gZenGlanceManager = new ZenGlanceManager();
|
||||
|
||||
// Register window actors if needed
|
||||
function registerWindowActors() {
|
||||
if (Services.prefs.getBoolPref('zen.glance.enabled', true)) {
|
||||
gZenActorsManager.addJSWindowActor('ZenGlance', {
|
||||
@@ -588,6 +614,5 @@
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
registerWindowActors();
|
||||
}
|
||||
|
Reference in New Issue
Block a user