From 43c98b7ddd78ff4c1beedf4348021da1ca63c071 Mon Sep 17 00:00:00 2001 From: Slowlife01 Date: Sun, 2 Mar 2025 19:21:32 +0700 Subject: [PATCH 001/127] hide empty tab from add-ons --- .../extensions/parent/ext-browser-js.patch | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/browser/components/extensions/parent/ext-browser-js.patch diff --git a/src/browser/components/extensions/parent/ext-browser-js.patch b/src/browser/components/extensions/parent/ext-browser-js.patch new file mode 100644 index 000000000..6e7d15fb3 --- /dev/null +++ b/src/browser/components/extensions/parent/ext-browser-js.patch @@ -0,0 +1,15 @@ +diff --git a/browser/components/extensions/parent/ext-browser.js b/browser/components/extensions/parent/ext-browser.js +index 179816fa96ccf26604d52f71232296398dd9bdbd..c35814bae4eab774892af1f6df7465601d4f87ac 100644 +--- a/browser/components/extensions/parent/ext-browser.js ++++ b/browser/components/extensions/parent/ext-browser.js +@@ -1218,6 +1218,10 @@ class TabManager extends TabManagerBase { + } + + canAccessTab(nativeTab) { ++ if (nativeTab.hasAttribute("zen-empty-tab")) { ++ return false ++ } ++ + // Check private browsing access at browser window level. + if (!this.extension.canAccessWindow(nativeTab.ownerGlobal)) { + return false; From d415bde66c89d9d6f362cf3b8035d12c6017eb61 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sun, 2 Mar 2025 16:45:57 +0100 Subject: [PATCH 002/127] Implement drag-and-drop functionality for split view and refine CSS styles for better layout and visibility --- .../content/main-popupset-inc-xhtml.patch | 8 +- .../base/content/zen-styles/zen-decks.css | 31 ++++ .../content/zen-styles/zen-workspaces.css | 1 + .../base/zen-components/ZenSidebarManager.mjs | 2 +- .../base/zen-components/ZenViewSplitter.mjs | 154 ++++++++++++++++-- src/browser/themes/shared/zen-icons/icons.css | 5 +- 6 files changed, 177 insertions(+), 24 deletions(-) diff --git a/src/browser/base/content/main-popupset-inc-xhtml.patch b/src/browser/base/content/main-popupset-inc-xhtml.patch index 1ebbd1437..a49f1bef7 100644 --- a/src/browser/base/content/main-popupset-inc-xhtml.patch +++ b/src/browser/base/content/main-popupset-inc-xhtml.patch @@ -1,8 +1,8 @@ diff --git a/browser/base/content/main-popupset.inc.xhtml b/browser/base/content/main-popupset.inc.xhtml -index e5f3424eaeeec0ba552537f167dd99e912216d94..4bdfcdb23fe9c44ad3d4de273c64f4cc31cb4034 100644 +index 959c523b21c642f29353b9de37b3ce6b5505b01b..0d151ad345dde47467432196ed76f4320b4b92cc 100644 --- a/browser/base/content/main-popupset.inc.xhtml +++ b/browser/base/content/main-popupset.inc.xhtml -@@ -181,6 +181,10 @@ +@@ -206,6 +206,10 @@ hidden="true" tabspecific="true" aria-labelledby="editBookmarkPanelTitle"> @@ -13,7 +13,7 @@ index e5f3424eaeeec0ba552537f167dd99e912216d94..4bdfcdb23fe9c44ad3d4de273c64f4cc -@@ -206,6 +210,7 @@ +@@ -231,6 +235,7 @@ class="footer-button"/> @@ -21,7 +21,7 @@ index e5f3424eaeeec0ba552537f167dd99e912216d94..4bdfcdb23fe9c44ad3d4de273c64f4cc -@@ -535,6 +540,8 @@ +@@ -565,6 +570,8 @@ #include popup-notifications.inc.xhtml diff --git a/src/browser/base/content/zen-styles/zen-decks.css b/src/browser/base/content/zen-styles/zen-decks.css index 1d087082a..dbd8f4f77 100644 --- a/src/browser/base/content/zen-styles/zen-decks.css +++ b/src/browser/base/content/zen-styles/zen-decks.css @@ -248,3 +248,34 @@ outline-color: var(--toolbarbutton-active-outline-color); } } + +#zen-split-view-fake-browser { + position: absolute; + height: 100%; + background: rgba(255, 255, 255, 0.1); + border-radius: var(--zen-native-inner-radius); + box-shadow: var(--zen-big-shadow); + pointer-events: none; + overflow: hidden; + + &::after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 3.5rem; + height: 3.5rem; + background: var(--zen-split-view-fake-icon); + background-size: contain; + background-repeat: no-repeat; + background-position: center; + opacity: 0.8; + transition: opacity 0.2s; + transition-delay: 0.1s; + + @starting-style { + opacity: 0; + } + } +} diff --git a/src/browser/base/content/zen-styles/zen-workspaces.css b/src/browser/base/content/zen-styles/zen-workspaces.css index 786b2dd8e..5b9ce55d5 100644 --- a/src/browser/base/content/zen-styles/zen-workspaces.css +++ b/src/browser/base/content/zen-styles/zen-workspaces.css @@ -9,6 +9,7 @@ justify-content: center; align-items: center; display: flex; + font-size: x-small; position: relative; diff --git a/src/browser/base/zen-components/ZenSidebarManager.mjs b/src/browser/base/zen-components/ZenSidebarManager.mjs index f4b2c4ab0..e734dddbf 100644 --- a/src/browser/base/zen-components/ZenSidebarManager.mjs +++ b/src/browser/base/zen-components/ZenSidebarManager.mjs @@ -102,7 +102,7 @@ class ZenBrowserManagerSidebar extends ZenDOMOperatedFeature { syncPinnedState() { const sidebar = document.getElementById('zen-sidebar-web-panel'); const pinButton = document.getElementById('zen-sidebar-web-panel-pinned'); - + if (sidebar.hasAttribute('pinned')) { pinButton.setAttribute('pinned', 'true'); } else { diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index a863ec023..68fee3cd2 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -84,6 +84,10 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { this.initializeContextMenu(); this.insertPageActionButton(); this.insertIntoContextMenu(); + + // Add drag over listener to the browser view + this.tabBrowserPanel.addEventListener('dragenter', this.onBrowserDragOverToSplit.bind(this)); + this.tabBrowserPanel.addEventListener('dragleave', this.onBrowserDragEndToSplit.bind(this)); } insertIntoContextMenu() { @@ -142,6 +146,111 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { } } + onBrowserDragOverToSplit(event) { + var dt = event.dataTransfer; + var draggedTab; + if (dt.mozTypesAt(0)[0] == TAB_DROP_TYPE) { + // tab copy or move + draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0); + // not our drop then + if (!draggedTab || gBrowser.selectedTab.hasAttribute('zen-empty-tab')) { + return; + } + draggedTab.container._finishMoveTogetherSelectedTabs(draggedTab); + } + if (!draggedTab || this._canDrop || this._hasAnimated || this.fakeBrowser) { + return; + } + const currentView = this._data[this.currentView]; + if (currentView?.tabs.length >= this.MAX_TABS) { + return; + } + this._canDrop = true; + // wait some time before showing the split view + this._showSplitViewTimeout = setTimeout(() => { + this._hasAnimated = true; + const panelsWidth = gBrowser.tabbox.getBoundingClientRect().width; + const halfWidth = panelsWidth / 2; + this.fakeBrowser = document.createXULElement('vbox'); + const padding = Services.prefs.getIntPref('zen.theme.content-element-separation', 0); + this.fakeBrowser.setAttribute('flex', '1'); + this.fakeBrowser.id = 'zen-split-view-fake-browser'; + gBrowser.tabbox.appendChild(this.fakeBrowser); + this.fakeBrowser.style.setProperty('--zen-split-view-fake-icon', `url(${draggedTab.getAttribute('image')})`); + Promise.all([ + gZenUIManager.motion.animate( + gBrowser.tabbox, + { + paddingLeft: [0, `${halfWidth}px`], + }, + { + duration: 0.1, + easing: 'ease-out', + } + ), + gZenUIManager.motion.animate( + this.fakeBrowser, + { + width: [0, `${halfWidth - padding * 2}px`], + marginLeft: [0, `${-(halfWidth - padding)}px`], + }, + { + duration: 0.1, + easing: 'ease-out', + } + ), + ]).then(() => {}); + }, 100); + } + + onBrowserDragEndToSplit(event) { + if (!this._canDrop) { + return; + } + const panelsRect = gBrowser.tabbox.getBoundingClientRect(); + // this event is fired even though we are still in the "allowed" area + if (event.target !== this.tabBrowserPanel) { + return; + } + this._canDrop = false; + if (this._showSplitViewTimeout) { + clearTimeout(this._showSplitViewTimeout); + } + if (!this._hasAnimated) { + return; + } + setTimeout(() => { + const panelsWidth = panelsRect.width; + const halfWidth = panelsWidth / 2; + const padding = Services.prefs.getIntPref('zen.theme.content-element-separation', 0); + Promise.all([ + gZenUIManager.motion.animate( + gBrowser.tabbox, + { + paddingLeft: [`${halfWidth}px`, 0], + }, + { + duration: 0.1, + easing: 'ease-out', + } + ), + gZenUIManager.motion.animate( + this.fakeBrowser, + { + width: [`${halfWidth - padding * 2}px`, 0], + marginLeft: [`${-(halfWidth - padding)}px`, 0], + }, + { + duration: 0.1, + easing: 'ease-out', + } + ), + ]).then(() => { + this._mayabeRemoveFakeBrowser(); + }); + }, 100); + } + /** * Remove a SplitNode from its tree and the view * @param {SplitNode} toRemove @@ -699,6 +808,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { this.updateSplitView(tab); tab.linkedBrowser.docShellIsActive = true; } + this._mayabeRemoveFakeBrowser(); } /** @@ -1282,6 +1392,16 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { } }; + _mayabeRemoveFakeBrowser() { + if (this.fakeBrowser) { + this.fakeBrowser.remove(); + this.fakeBrowser = null; + gBrowser.tabbox.removeAttribute('style'); + delete this._canDrop; + delete this._hasAnimated; + } + } + /** * @description moves the tab to the split view if dragged on a browser * @param event - The event @@ -1289,6 +1409,8 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { * @returns {boolean} true if the tab was moved to the split view */ moveTabToSplitView(event, draggedTab) { + this._mayabeRemoveFakeBrowser(); + const dropTarget = document.elementFromPoint(event.clientX, event.clientY); const browser = dropTarget?.closest('browser'); @@ -1336,24 +1458,22 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { } } else { // Create new split view with layout based on drop position - let gridType; - switch (hoverSide) { - case 'left': - case 'right': - gridType = 'vsep'; - break; - case 'top': - case 'bottom': - gridType = 'hsep'; - break; - default: - gridType = 'grid'; - } + let gridType = 'vsep'; + //switch (hoverSide) { + // case 'left': + // case 'right': + // gridType = 'vsep'; + // break; + // case 'top': + // case 'bottom': + // gridType = 'hsep'; + // break; + // default: + // gridType = 'grid'; + //} - // Put tabs in correct order based on drop side - const tabs = ['left', 'top'].includes(hoverSide) ? [draggedTab, droppedOnTab] : [droppedOnTab, draggedTab]; - - this.splitTabs(tabs, gridType); + // Put tabs always as if it was dropped from the left + this.splitTabs([draggedTab, droppedOnTab], gridType); } } return true; diff --git a/src/browser/themes/shared/zen-icons/icons.css b/src/browser/themes/shared/zen-icons/icons.css index 320f5add2..32e8e7838 100644 --- a/src/browser/themes/shared/zen-icons/icons.css +++ b/src/browser/themes/shared/zen-icons/icons.css @@ -1140,6 +1140,7 @@ menupopup > menuitem:is([type='checkbox']) .menu-iconic-left { } #toolbar-context-toggle-vertical-tabs, -#toolbar-context-customize-sidebar { - display: none; +#toolbar-context-customize-sidebar, +#sidebarRevampSeparator { + display: none !important; } From 7b124f1dc2c59f301d6ae81c90fd71fe28cacf3b Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sun, 2 Mar 2025 17:03:58 +0100 Subject: [PATCH 003/127] Add preference to hide one-off search buttons and adjust CSS positioning --- configs/common/mozconfig | 1 - src/browser/app/profile/zen-browser.js | 1 + src/browser/base/content/zen-styles/zen-urlbar.css | 3 +-- .../components/search/SearchOneOffs-sys-mjs.patch | 13 +++++++++++++ 4 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 src/browser/components/search/SearchOneOffs-sys-mjs.patch diff --git a/configs/common/mozconfig b/configs/common/mozconfig index 11e8d91cb..00c55a046 100644 --- a/configs/common/mozconfig +++ b/configs/common/mozconfig @@ -59,7 +59,6 @@ if test "$ZEN_RELEASE"; then ac_add_options --disable-rust-tests ac_add_options --disable-default-browser-agent -# ac_add_options --enable-minify=js,properties if ! test "$ZEN_DISABLE_LTO"; then # only enable full LTO when ZEN_RELEASE_BRANCH is 'release' diff --git a/src/browser/app/profile/zen-browser.js b/src/browser/app/profile/zen-browser.js index 6aa60481a..630930c8c 100644 --- a/src/browser/app/profile/zen-browser.js +++ b/src/browser/app/profile/zen-browser.js @@ -121,6 +121,7 @@ pref('zen.urlbar.replace-newtab', true); pref('zen.urlbar.behavior', 'floating-on-type'); // default, floating-on-type, float pref('zen.urlbar.wait-to-clear', 45000); // in ms (default 45s) pref('zen.urlbar.show-domain-only-in-sidebar', true); +pref('zen.urlbar.hide-one-offs', true); #ifdef XP_MACOSX // Disable for macos in the meantime until @HarryHeres finds a solution for hight DPI screens diff --git a/src/browser/base/content/zen-styles/zen-urlbar.css b/src/browser/base/content/zen-styles/zen-urlbar.css index 94aee0b47..92680874b 100644 --- a/src/browser/base/content/zen-styles/zen-urlbar.css +++ b/src/browser/base/content/zen-styles/zen-urlbar.css @@ -435,9 +435,8 @@ button.popup-notification-dropmarker { font-size: 1.5em !important; width: min(90%, 60rem) !important; } - top: 50vh !important; + top: 25vh !important; transform: translateX(-50%); - margin-top: -20%; left: 50% !important; #urlbar-container:has(&) { diff --git a/src/browser/components/search/SearchOneOffs-sys-mjs.patch b/src/browser/components/search/SearchOneOffs-sys-mjs.patch new file mode 100644 index 000000000..2ec4565cb --- /dev/null +++ b/src/browser/components/search/SearchOneOffs-sys-mjs.patch @@ -0,0 +1,13 @@ +diff --git a/browser/components/search/SearchOneOffs.sys.mjs b/browser/components/search/SearchOneOffs.sys.mjs +index 6dcd68f7ec4da72f9510ac3c8ff1cecffbd70e92..f712b95d03be46f7d81bad4113f533f0515a92b9 100644 +--- a/browser/components/search/SearchOneOffs.sys.mjs ++++ b/browser/components/search/SearchOneOffs.sys.mjs +@@ -446,7 +446,7 @@ export class SearchOneOffs { + // For the search-bar, always show the one-off buttons where there is an + // option to add an engine. + let addEngineNeeded = isSearchBar && addEngines.length; +- let hideOneOffs = (await this.willHide()) && !addEngineNeeded; ++ let hideOneOffs = (await this.willHide()) && !addEngineNeeded || Services.prefs.getBoolPref("zen.urlbar.hide-one-offs"); + + // The _engineInfo cache is used by more consumers, thus it is not a good + // representation of whether this method already updated the one-off buttons From 780b514cc0b025c56eacb9d451290403d07f2289 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sun, 2 Mar 2025 17:11:18 +0100 Subject: [PATCH 004/127] Refine animation for browser wrapper opacity and adjust easing for smoother transitions --- src/browser/base/zen-components/ZenGlanceManager.mjs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/browser/base/zen-components/ZenGlanceManager.mjs b/src/browser/base/zen-components/ZenGlanceManager.mjs index 8040dd7c5..d075beae4 100644 --- a/src/browser/base/zen-components/ZenGlanceManager.mjs +++ b/src/browser/base/zen-components/ZenGlanceManager.mjs @@ -267,14 +267,15 @@ .then(() => { this.#currentParentTab.linkedBrowser.closest('.browserSidebarContainer').removeAttribute('style'); }); + this.browserWrapper.style.opacity = 1; gZenUIManager.motion .animate( this.browserWrapper, { ...originalPosition, - opacity: 0.3, + opacity: 0, }, - { type: 'spring', bounce: 0, duration: 0.4, easing: 'ease' } + { type: 'spring', bounce: 0, duration: 0.6, easing: 'ease-in' } ) .then(() => { this.browserWrapper.removeAttribute('animate'); From 9454ab9d6c7d9677ee2ce28203586795eb0047ec Mon Sep 17 00:00:00 2001 From: noaione Date: Mon, 3 Mar 2025 00:03:29 +0700 Subject: [PATCH 005/127] Report JXL frame counts properly Ref: - https://phabricator.services.mozilla.com/D212831 - https://github.com/zen-browser/desktop/pull/5634#issuecomment-2692802618 --- src/image/decoders/nsJXLDecoder-cpp.patch | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/image/decoders/nsJXLDecoder-cpp.patch b/src/image/decoders/nsJXLDecoder-cpp.patch index 91f45420c..b1fa5d0a2 100644 --- a/src/image/decoders/nsJXLDecoder-cpp.patch +++ b/src/image/decoders/nsJXLDecoder-cpp.patch @@ -1,5 +1,5 @@ diff --git a/image/decoders/nsJXLDecoder.cpp b/image/decoders/nsJXLDecoder.cpp -index ffb7f3cd51e1d0e480bf8ac5e936a90c11f0c93d..282472afe4fbab7d41adaf15928fa93c99e74452 100644 +index ffb7f3cd51e1d0e480bf8ac5e936a90c11f0c93d..946c0ff8c2b0ab295d500f131b65b07bbc7df032 100644 --- a/image/decoders/nsJXLDecoder.cpp +++ b/image/decoders/nsJXLDecoder.cpp @@ -45,9 +45,20 @@ nsJXLDecoder::nsJXLDecoder(RasterImage* aImage) @@ -65,7 +65,7 @@ index ffb7f3cd51e1d0e480bf8ac5e936a90c11f0c93d..282472afe4fbab7d41adaf15928fa93c while (true) { JxlDecoderStatus status = JxlDecoderProcessInput(mDecoder.get()); -@@ -106,51 +127,229 @@ LexerTransition nsJXLDecoder::ReadJXLData( +@@ -106,51 +127,238 @@ LexerTransition nsJXLDecoder::ReadJXLData( size_t remaining = JxlDecoderReleaseInput(mDecoder.get()); mBuffer.clear(); JXL_TRY_BOOL(mBuffer.append(aData + aLength - remaining, remaining)); @@ -105,7 +105,9 @@ index ffb7f3cd51e1d0e480bf8ac5e936a90c11f0c93d..282472afe4fbab7d41adaf15928fa93c PostSize(mInfo.xsize, mInfo.ysize); + if (WantsFrameCount()) { - PostFrameCount(/* aFrameCount */ 1); +- PostFrameCount(/* aFrameCount */ 1); ++ // We start at 1 as additional frames are added in ++ PostFrameCount(1); } + if (mInfo.alpha_bits > 0) { @@ -293,6 +295,10 @@ index ffb7f3cd51e1d0e480bf8ac5e936a90c11f0c93d..282472afe4fbab7d41adaf15928fa93c + !mFrameHeader.is_last) { + mNumFrames++; + mContinue = true; ++ if (WantsFrameCount()) { ++ // If we want frame count, report it now. ++ PostFrameCount(mNumFrames + 1); ++ } + // Notify for a new frame but there may be data in the current buffer + // that can immediately be processed. + return Transition::ToAfterYield(State::JXL_DATA); @@ -301,6 +307,10 @@ index ffb7f3cd51e1d0e480bf8ac5e936a90c11f0c93d..282472afe4fbab7d41adaf15928fa93c + } + + case JXL_DEC_SUCCESS: { ++ // Decoding is done. Report the full frame count. ++ if (WantsFrameCount()) { ++ PostFrameCount(mNumFrames); ++ } + PostLoopCount(HasAnimation() ? (int32_t)mInfo.animation.num_loops - 1 + : 0); PostDecodeDone(); From 7cb1ae6d3c3a89493a90d58d308d906d2ab36b7a Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Sun, 2 Mar 2025 18:21:18 +0100 Subject: [PATCH 006/127] Fixed compact mode sidebar animating on an empty state and not animating properly --- src/browser/base/content/zen-styles/zen-compact-mode.css | 8 +++++--- src/browser/base/zen-components/ZenCompactMode.mjs | 7 +++++-- src/browser/base/zen-components/ZenWorkspaces.mjs | 1 + 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-compact-mode.css b/src/browser/base/content/zen-styles/zen-compact-mode.css index 32d9fca83..6fac7e8ad 100644 --- a/src/browser/base/content/zen-styles/zen-compact-mode.css +++ b/src/browser/base/content/zen-styles/zen-compact-mode.css @@ -113,6 +113,7 @@ & #urlbar[open][zen-floating-urlbar='true'] { transition: left 0.05s ease; + visibility: visible; #navigator-toolbox:has(&) { opacity: 1; @@ -134,17 +135,18 @@ } } - #navigator-toolbox[zen-has-hover], + #navigator-toolbox[zen-has-hover]:not(:has(#urlbar[zen-floating-urlbar='true']:hover)), #navigator-toolbox[zen-user-show], + #navigator-toolbox[zen-has-empty-tab], #navigator-toolbox[flash-popup], #navigator-toolbox[has-popup-menu], #navigator-toolbox[movingtab], #navigator-toolbox:has(.tabbrowser-tab:active), &[zen-renaming-tab='true'] #navigator-toolbox, #navigator-toolbox:has( - *:is([panelopen='true'], [open='true'], #urlbar:not([zen-floating-urlbar='true']):focus-within):not(tab):not(.zen-compact-mode-ignore) + *:is([panelopen='true'], [open='true'], #urlbar:focus-within):not(#urlbar[zen-floating-urlbar='true']):not(tab):not(.zen-compact-mode-ignore) ) { - &:not([animate='true']):not(:has(#urlbar[zen-floating-urlbar='true']:hover)) { + &:not([animate='true']) { --zen-compact-mode-func: linear( 0 0%, 0.002748 1%, diff --git a/src/browser/base/zen-components/ZenCompactMode.mjs b/src/browser/base/zen-components/ZenCompactMode.mjs index f5463c081..a88b25032 100644 --- a/src/browser/base/zen-components/ZenCompactMode.mjs +++ b/src/browser/base/zen-components/ZenCompactMode.mjs @@ -158,6 +158,7 @@ var gZenCompactModeManager = { const canAnimate = lazyCompactMode.COMPACT_MODE_CAN_ANIMATE_SIDEBAR && !this.sidebar.hasAttribute('zen-user-show') && + !this.sidebar.hasAttribute('zen-has-empty-tab') && !this.sidebar.hasAttribute('zen-has-hover'); // Do this so we can get the correct width ONCE compact mode styled have been applied if (canAnimate) { @@ -191,15 +192,17 @@ var gZenCompactModeManager = { ) .then(() => { window.requestAnimationFrame(() => { + this.sidebar.style.transition = 'none'; this.sidebar.removeAttribute('animate'); + this.sidebar.style.visibility = 'hidden'; this.sidebar.style.removeProperty('margin-right'); this.sidebar.style.removeProperty('margin-left'); this.sidebar.style.removeProperty('transform'); - this.sidebar.style.transition = 'none'; setTimeout(() => { this._animating = false; + this.sidebar.style.removeProperty('visibility'); this.sidebar.style.removeProperty('transition'); - }); + }, 300); }); }); } else if (canHideSidebar && !isCompactMode) { diff --git a/src/browser/base/zen-components/ZenWorkspaces.mjs b/src/browser/base/zen-components/ZenWorkspaces.mjs index e1cf0a825..3d7a7a530 100644 --- a/src/browser/base/zen-components/ZenWorkspaces.mjs +++ b/src/browser/base/zen-components/ZenWorkspaces.mjs @@ -1967,6 +1967,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { } async onLocationChange(browser) { + gZenCompactModeManager.sidebar.toggleAttribute('zen-has-empty-tab', gBrowser.selectedTab.hasAttribute('zen-empty-tab')); if (!this.workspaceEnabled || this._inChangingWorkspace || this._isClosingWindow) { return; } From 0cb7b0af95c2d0a0cc077f75e3da020642cc9931 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sun, 2 Mar 2025 21:36:31 +0100 Subject: [PATCH 007/127] Refactor tab management and drag-and-drop functionality; improve animation durations and conditions for splitting tabs. --- .../base/content/zen-styles/zen-decks.css | 1 - .../zen-components/ZenPinnedTabManager.mjs | 5 +- .../base/zen-components/ZenViewSplitter.mjs | 52 +++++++++++--- .../tabbrowser/content/tabbrowser-js.patch | 69 ++++++++++--------- .../tabbrowser/content/tabs-js.patch | 4 +- 5 files changed, 82 insertions(+), 49 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-decks.css b/src/browser/base/content/zen-styles/zen-decks.css index dbd8f4f77..edb94880e 100644 --- a/src/browser/base/content/zen-styles/zen-decks.css +++ b/src/browser/base/content/zen-styles/zen-decks.css @@ -255,7 +255,6 @@ background: rgba(255, 255, 255, 0.1); border-radius: var(--zen-native-inner-radius); box-shadow: var(--zen-big-shadow); - pointer-events: none; overflow: hidden; &::after { diff --git a/src/browser/base/zen-components/ZenPinnedTabManager.mjs b/src/browser/base/zen-components/ZenPinnedTabManager.mjs index 82f90009a..66596d595 100644 --- a/src/browser/base/zen-components/ZenPinnedTabManager.mjs +++ b/src/browser/base/zen-components/ZenPinnedTabManager.mjs @@ -600,7 +600,10 @@ } addToEssentials(tab) { - const tabs = tab ? [tab] : TabContextMenu.contextTab.multiselected ? gBrowser.selectedTabs : [TabContextMenu.contextTab]; + const tabs = tab ? ( + // if it's already an array, dont make it [tab] + tab?.length ? tab : [tab] + ) : TabContextMenu.contextTab.multiselected ? gBrowser.selectedTabs : [TabContextMenu.contextTab]; for (let i = 0; i < tabs.length; i++) { const tab = tabs[i]; if (tab.hasAttribute('zen-essential')) { diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index 68fee3cd2..4d200bb81 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -86,8 +86,9 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { this.insertIntoContextMenu(); // Add drag over listener to the browser view - this.tabBrowserPanel.addEventListener('dragenter', this.onBrowserDragOverToSplit.bind(this)); - this.tabBrowserPanel.addEventListener('dragleave', this.onBrowserDragEndToSplit.bind(this)); + const tabBox = document.getElementById('tabbrowser-tabbox'); + tabBox.addEventListener('dragenter', this.onBrowserDragOverToSplit.bind(this)); + tabBox.addEventListener('dragleave', this.onBrowserDragEndToSplit.bind(this)); } insertIntoContextMenu() { @@ -148,6 +149,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { onBrowserDragOverToSplit(event) { var dt = event.dataTransfer; + const dragEffect = dt.dropEffect; var draggedTab; if (dt.mozTypesAt(0)[0] == TAB_DROP_TYPE) { // tab copy or move @@ -161,6 +163,9 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { if (!draggedTab || this._canDrop || this._hasAnimated || this.fakeBrowser) { return; } + if (draggedTab.splitView) { + return; + } const currentView = this._data[this.currentView]; if (currentView?.tabs.length >= this.MAX_TABS) { return; @@ -184,7 +189,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { paddingLeft: [0, `${halfWidth}px`], }, { - duration: 0.1, + duration: 0.15, easing: 'ease-out', } ), @@ -195,7 +200,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { marginLeft: [0, `${-(halfWidth - padding)}px`], }, { - duration: 0.1, + duration: 0.15, easing: 'ease-out', } ), @@ -209,7 +214,8 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { } const panelsRect = gBrowser.tabbox.getBoundingClientRect(); // this event is fired even though we are still in the "allowed" area - if (event.target !== this.tabBrowserPanel) { + console.log(event.target); + if (event.target !== gBrowser.tabbox && event.target !== this.fakeBrowser) { return; } this._canDrop = false; @@ -230,7 +236,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { paddingLeft: [`${halfWidth}px`, 0], }, { - duration: 0.1, + duration: 0.15, easing: 'ease-out', } ), @@ -241,7 +247,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { marginLeft: [`${-(halfWidth - padding)}px`, 0], }, { - duration: 0.1, + duration: 0.15, easing: 'ease-out', } ), @@ -817,14 +823,27 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { * @param {Tab[]} tabs - The tabs to split. * @param {string} gridType - The type of grid layout. */ - splitTabs(tabs, gridType) { - const firstisPinned = tabs[0].pinned; + splitTabs(tabs, gridType, initialIndex = 0) { tabs = tabs.filter( - (t) => t.pinned === firstisPinned && !t.hidden && !t.hasAttribute('zen-empty-tab') && !t.hasAttribute('zen-essential') + (t) => !t.hidden && !t.hasAttribute('zen-empty-tab') ); if (tabs.length < 2 || tabs.length > this.MAX_TABS) { return; } + const firstIsPinned = tabs[initialIndex].pinned; + const firstIsEssential = tabs[initialIndex].hasAttribute('zen-essential'); + const oddOnes = tabs.filter((t) => t.pinned !== firstIsPinned || t.hasAttribute('zen-essential') != firstIsEssential); + if (firstIsEssential) { + gZenPinnedTabManager.addToEssentials(oddOnes); + } else { + for (const tab of oddOnes) { + if (firstIsPinned) { + gBrowser.pinTab(tab); + } else { + gBrowser.unpinTab(tab); + } + } + } const existingSplitTab = tabs.find((tab) => tab.splitView); if (existingSplitTab) { @@ -1473,7 +1492,18 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { //} // Put tabs always as if it was dropped from the left - this.splitTabs([draggedTab, droppedOnTab], gridType); + this.splitTabs([draggedTab, droppedOnTab], gridType, 1); + if (draggedTab.linkedBrowser) { + gZenUIManager.motion.animate(draggedTab.linkedBrowser.closest('.browserSidebarContainer'), { + scale: [0.98, 1], + opacity: [0, 1], + }, { + type: 'spring', + bounce: 0.6, + duration: 0.5, + delay: 0.1, + }); + } } } return true; diff --git a/src/browser/components/tabbrowser/content/tabbrowser-js.patch b/src/browser/components/tabbrowser/content/tabbrowser-js.patch index 77d7c2bcc..90b4ac070 100644 --- a/src/browser/components/tabbrowser/content/tabbrowser-js.patch +++ b/src/browser/components/tabbrowser/content/tabbrowser-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js -index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd71c4dfe1 100644 +index 628aa6596627c85efe361fc1ece8fd58f7ee653e..372a783210c5829533eb8c2b3ca32a370be5f820 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js @@ -412,11 +412,50 @@ @@ -246,7 +246,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd } = {} ) { if (!tabs?.length) { -@@ -2918,7 +2991,11 @@ +@@ -2918,7 +2991,12 @@ id = `${Date.now()}-${Math.round(Math.random() * 100)}`; } let group = this._createTabGroup(id, color, false, label); @@ -254,12 +254,13 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd + if (forSplitView) { + group.setAttribute('split-view-group', true); + } -+ group.pinned = tabs.some(tab => tab.pinned); -+ (group.pinned ? this.verticalPinnedTabsContainer : this.tabContainer).insertBefore( ++ group.essential = tabs.some(tab => tab.hasAttribute("essential")); ++ group.pinned = group.essential || tabs.some(tab => tab.pinned); ++ (group.essential ? document.getElementById("zen-essentials-container") : (group.pinned ? this.verticalPinnedTabsContainer : this.tabContainer)).insertBefore( group, insertBefore?.group ?? insertBefore ); -@@ -3126,6 +3203,7 @@ +@@ -3126,6 +3204,7 @@ initialBrowsingContextGroupId, openWindowInfo, skipLoad, @@ -267,7 +268,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd } ) { // If we don't have a preferred remote type, and we have a remote -@@ -3189,6 +3267,7 @@ +@@ -3189,6 +3268,7 @@ openWindowInfo, name, skipLoad, @@ -275,7 +276,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd }); } -@@ -3367,6 +3446,24 @@ +@@ -3367,6 +3447,24 @@ ) { tabWasReused = true; tab = this.selectedTab; @@ -300,7 +301,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd if (!tabData.pinned) { this.unpinTab(tab); } else { -@@ -3380,6 +3477,7 @@ +@@ -3380,6 +3478,7 @@ restoreTabsLazily && !select && !tabData.pinned; let url = "about:blank"; @@ -308,7 +309,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd if (tabData.entries?.length) { let activeIndex = (tabData.index || tabData.entries.length) - 1; // Ensure the index is in bounds. -@@ -3415,7 +3513,24 @@ +@@ -3415,7 +3514,24 @@ skipLoad: true, preferredRemoteType, }); @@ -334,7 +335,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd if (select) { tabToSelect = tab; } -@@ -3428,8 +3543,8 @@ +@@ -3428,8 +3544,8 @@ // inserted in the DOM. If the tab is not yet in the DOM, // just insert it in the right place from the start. if (!tab.parentNode) { @@ -345,7 +346,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd tab.toggleAttribute("pinned", true); this.tabContainer._invalidateCachedTabs(); // Then ensure all the tab open/pinning information is sent. -@@ -3693,7 +3808,7 @@ +@@ -3693,7 +3809,7 @@ // Ensure we have an index if one was not provided. if (typeof index != "number") { // Move the new tab after another tab if needed, to the end otherwise. @@ -354,7 +355,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd if ( !bulkOrderedOpen && ((openerTab && -@@ -3736,18 +3851,18 @@ +@@ -3736,18 +3852,18 @@ // Ensure index is within bounds. if (tab.pinned) { @@ -377,7 +378,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd if (tabAfter && tabAfter.group == tabGroup) { // Place at the front of, or between tabs in, the same tab group this.tabContainer.insertBefore(tab, tabAfter); -@@ -4059,6 +4174,9 @@ +@@ -4059,6 +4175,9 @@ return; } @@ -387,7 +388,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd this.removeTabs(selectedTabs); } -@@ -4391,6 +4509,7 @@ +@@ -4391,6 +4510,7 @@ skipSessionStore, } = {} ) { @@ -395,7 +396,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd if (UserInteraction.running("browser.tabs.opening", window)) { UserInteraction.finish("browser.tabs.opening", window); } -@@ -4407,6 +4526,12 @@ +@@ -4407,6 +4527,12 @@ TelemetryStopwatch.start("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab); } @@ -408,7 +409,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd // Handle requests for synchronously removing an already // asynchronously closing tab. if (!animate && aTab.closing) { -@@ -4421,7 +4546,9 @@ +@@ -4421,7 +4547,9 @@ // frame created for it (for example, by updating the visually selected // state). let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width; @@ -419,7 +420,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd if ( !this._beginRemoveTab(aTab, { closeWindowFastpath: true, -@@ -4435,7 +4562,6 @@ +@@ -4435,7 +4563,6 @@ TelemetryStopwatch.cancel("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab); return; } @@ -427,7 +428,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd let lockTabSizing = !this.tabContainer.verticalMode && !aTab.pinned && -@@ -4574,14 +4700,14 @@ +@@ -4574,14 +4701,14 @@ !!this.tabsInCollapsedTabGroups.length; if ( aTab.visible && @@ -444,7 +445,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd if (closeWindow) { // We've already called beforeunload on all the relevant tabs if we get here, -@@ -4605,6 +4731,7 @@ +@@ -4605,6 +4732,7 @@ newTab = true; } @@ -452,7 +453,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd aTab._endRemoveArgs = [closeWindow, newTab]; // swapBrowsersAndCloseOther will take care of closing the window without animation. -@@ -4645,9 +4772,7 @@ +@@ -4645,9 +4773,7 @@ aTab._mouseleave(); if (newTab) { @@ -463,7 +464,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd } else { TabBarVisibility.update(); } -@@ -4776,6 +4901,8 @@ +@@ -4776,6 +4902,8 @@ this.tabs[i]._tPos = i; } @@ -472,7 +473,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd if (!this._windowIsClosing) { if (wasPinned) { this.tabContainer._positionPinnedTabs(); -@@ -4994,7 +5121,7 @@ +@@ -4994,7 +5122,7 @@ !excludeTabs.has(aTab.owner) && Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose") ) { @@ -481,7 +482,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd } // Try to find a remaining tab that comes after the given tab -@@ -5016,7 +5143,7 @@ +@@ -5016,7 +5144,7 @@ } if (tab) { @@ -490,7 +491,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd } // If no qualifying visible tab was found, see if there is a tab in -@@ -5434,10 +5561,10 @@ +@@ -5434,10 +5562,10 @@ SessionStore.deleteCustomTabValue(aTab, "hiddenBy"); } @@ -503,7 +504,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd aTab.selected || aTab.closing || // Tabs that are sharing the screen, microphone or camera cannot be hidden. -@@ -5675,7 +5802,7 @@ +@@ -5675,7 +5803,7 @@ // Don't allow mixing pinned and unpinned tabs. if (aTab.pinned) { @@ -512,7 +513,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd } else { aIndex = Math.max(aIndex, this.pinnedTabCount); } -@@ -5684,11 +5811,18 @@ +@@ -5684,11 +5812,18 @@ } this._handleTabMove(aTab, () => { @@ -534,16 +535,16 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd neighbor.after(aTab); } else { this.tabContainer.insertBefore(aTab, neighbor); -@@ -5697,7 +5831,7 @@ +@@ -5697,7 +5832,7 @@ } moveTabToGroup(aTab, aGroup) { - if (aTab.pinned) { -+ if (aTab.pinned != !!aGroup.pinned && !aTab.hasAttribute("zen-essential")) { ++ if (aTab.pinned != !!aGroup.pinned) { return; } if (aTab.group && aTab.group.id === aGroup.id) { -@@ -5721,6 +5855,8 @@ +@@ -5721,6 +5856,8 @@ moveActionCallback(); @@ -552,7 +553,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd // Clear tabs cache after moving nodes because the order of tabs may have // changed. this.tabContainer._invalidateCachedTabs(); -@@ -5771,7 +5907,7 @@ +@@ -5771,7 +5908,7 @@ createLazyBrowser, }; @@ -561,7 +562,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd if (aIndex < numPinned || (aTab.pinned && aIndex == numPinned)) { params.pinned = true; } -@@ -7415,6 +7551,7 @@ +@@ -7415,6 +7552,7 @@ aWebProgress.isTopLevel ) { this.mTab.setAttribute("busy", "true"); @@ -569,7 +570,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd gBrowser._tabAttrModified(this.mTab, ["busy"]); this.mTab._notselectedsinceload = !this.mTab.selected; } -@@ -8381,7 +8518,7 @@ var TabContextMenu = { +@@ -8381,7 +8519,7 @@ var TabContextMenu = { ); contextUnpinSelectedTabs.hidden = !this.contextTab.pinned || !multiselectionContext; @@ -578,7 +579,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd // Move Tab items let contextMoveTabOptions = document.getElementById( "context_moveTabOptions" -@@ -8414,7 +8551,7 @@ var TabContextMenu = { +@@ -8414,7 +8552,7 @@ var TabContextMenu = { let contextMoveTabToStart = document.getElementById("context_moveToStart"); let isFirstTab = tabsToMove[0] == visibleTabs[0] || @@ -587,7 +588,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f4a4ad413785e08bbb70df8cbb5feefd contextMoveTabToStart.disabled = isFirstTab && allSelectedTabsAdjacent; document.getElementById("context_openTabInWindow").disabled = -@@ -8647,6 +8784,7 @@ var TabContextMenu = { +@@ -8647,6 +8785,7 @@ var TabContextMenu = { if (this.contextTab.multiselected) { gBrowser.removeMultiSelectedTabs(); } else { diff --git a/src/browser/components/tabbrowser/content/tabs-js.patch b/src/browser/components/tabbrowser/content/tabs-js.patch index fa88040a7..978a13e6c 100644 --- a/src/browser/components/tabbrowser/content/tabs-js.patch +++ b/src/browser/components/tabbrowser/content/tabs-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js -index fa96568d366fd3608f9bd583fa793150bd815c8b..9a288957781277246b66a911590a13e7231958d0 100644 +index fa96568d366fd3608f9bd583fa793150bd815c8b..37644a42ac426c2a48e28056654eb654ffa660e4 100644 --- a/browser/components/tabbrowser/content/tabs.js +++ b/browser/components/tabbrowser/content/tabs.js @@ -94,7 +94,7 @@ @@ -103,7 +103,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..9a288957781277246b66a911590a13e7 - this._finishMoveTogetherSelectedTabs(draggedTab); this._finishAnimateTabMove(); -+ if (event.ctrlKey && !dt.mozUserCancelled && dt.dropEffect == "none" && !this._isCustomizing) { ++ if ((event.ctrlKey || event.metaKey) && !dt.mozUserCancelled && dt.dropEffect == "none" && !this._isCustomizing) { + const moved = gZenViewSplitter.moveTabToSplitView(event, draggedTab); + if (moved) { + delete draggedTab._dragData; From 7ca57da6fee3009326e24094a92f7ac439fd4de6 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sun, 2 Mar 2025 21:36:53 +0100 Subject: [PATCH 008/127] Refactor tab addition logic and streamline tab filtering in Zen components --- .../zen-components/ZenPinnedTabManager.mjs | 12 ++++++--- .../base/zen-components/ZenViewSplitter.mjs | 26 ++++++++++--------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/browser/base/zen-components/ZenPinnedTabManager.mjs b/src/browser/base/zen-components/ZenPinnedTabManager.mjs index 66596d595..c8ac86c2d 100644 --- a/src/browser/base/zen-components/ZenPinnedTabManager.mjs +++ b/src/browser/base/zen-components/ZenPinnedTabManager.mjs @@ -600,10 +600,14 @@ } addToEssentials(tab) { - const tabs = tab ? ( - // if it's already an array, dont make it [tab] - tab?.length ? tab : [tab] - ) : TabContextMenu.contextTab.multiselected ? gBrowser.selectedTabs : [TabContextMenu.contextTab]; + const tabs = tab + ? // if it's already an array, dont make it [tab] + tab?.length + ? tab + : [tab] + : TabContextMenu.contextTab.multiselected + ? gBrowser.selectedTabs + : [TabContextMenu.contextTab]; for (let i = 0; i < tabs.length; i++) { const tab = tabs[i]; if (tab.hasAttribute('zen-essential')) { diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index 4d200bb81..13c319ed8 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -824,9 +824,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { * @param {string} gridType - The type of grid layout. */ splitTabs(tabs, gridType, initialIndex = 0) { - tabs = tabs.filter( - (t) => !t.hidden && !t.hasAttribute('zen-empty-tab') - ); + tabs = tabs.filter((t) => !t.hidden && !t.hasAttribute('zen-empty-tab')); if (tabs.length < 2 || tabs.length > this.MAX_TABS) { return; } @@ -1494,15 +1492,19 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { // Put tabs always as if it was dropped from the left this.splitTabs([draggedTab, droppedOnTab], gridType, 1); if (draggedTab.linkedBrowser) { - gZenUIManager.motion.animate(draggedTab.linkedBrowser.closest('.browserSidebarContainer'), { - scale: [0.98, 1], - opacity: [0, 1], - }, { - type: 'spring', - bounce: 0.6, - duration: 0.5, - delay: 0.1, - }); + gZenUIManager.motion.animate( + draggedTab.linkedBrowser.closest('.browserSidebarContainer'), + { + scale: [0.98, 1], + opacity: [0, 1], + }, + { + type: 'spring', + bounce: 0.6, + duration: 0.5, + delay: 0.1, + } + ); } } } From b83ec80e7c5f5e1b59a1e1b7e43f04097df2ad4d Mon Sep 17 00:00:00 2001 From: noaione Date: Mon, 3 Mar 2025 03:48:18 +0700 Subject: [PATCH 009/127] Ensure we check if we have animation or not first --- src/image/decoders/nsJXLDecoder-cpp.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/image/decoders/nsJXLDecoder-cpp.patch b/src/image/decoders/nsJXLDecoder-cpp.patch index b1fa5d0a2..2f3adf7cd 100644 --- a/src/image/decoders/nsJXLDecoder-cpp.patch +++ b/src/image/decoders/nsJXLDecoder-cpp.patch @@ -1,5 +1,5 @@ diff --git a/image/decoders/nsJXLDecoder.cpp b/image/decoders/nsJXLDecoder.cpp -index ffb7f3cd51e1d0e480bf8ac5e936a90c11f0c93d..946c0ff8c2b0ab295d500f131b65b07bbc7df032 100644 +index ffb7f3cd51e1d0e480bf8ac5e936a90c11f0c93d..378ae56d7fa99fbe8bdea2e689949994bbdf8034 100644 --- a/image/decoders/nsJXLDecoder.cpp +++ b/image/decoders/nsJXLDecoder.cpp @@ -45,9 +45,20 @@ nsJXLDecoder::nsJXLDecoder(RasterImage* aImage) @@ -309,7 +309,7 @@ index ffb7f3cd51e1d0e480bf8ac5e936a90c11f0c93d..946c0ff8c2b0ab295d500f131b65b07b + case JXL_DEC_SUCCESS: { + // Decoding is done. Report the full frame count. + if (WantsFrameCount()) { -+ PostFrameCount(mNumFrames); ++ PostFrameCount(mInfo.have_animation ? mNumFrames + 1 : 1); + } + PostLoopCount(HasAnimation() ? (int32_t)mInfo.animation.num_loops - 1 + : 0); From 8aaccf06b2f2284697b12bc7ce4c413b9bfb71c4 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Mon, 3 Mar 2025 00:11:31 +0100 Subject: [PATCH 010/127] Enhance tab selection handling and improve drag-and-drop functionality in ZenViewSplitter --- .../base/zen-components/ZenViewSplitter.mjs | 38 +++++++++++++++++-- .../tabbrowser/content/tabs-js.patch | 4 +- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index 13c319ed8..645f34797 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -69,6 +69,8 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { _edgeHoverSize; minResizeWidth; + _lastOpenedTab = null; + MAX_TABS = 4; init() { @@ -81,6 +83,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { ChromeUtils.defineLazyGetter(this, 'dropZone', () => document.getElementById('zen-splitview-dropzone')); window.addEventListener('TabClose', this.handleTabClose.bind(this)); + window.addEventListener('TabSelect', this.onTabSelect.bind(this)); this.initializeContextMenu(); this.insertPageActionButton(); this.insertIntoContextMenu(); @@ -107,6 +110,9 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { */ handleTabClose(event) { const tab = event.target; + if (tab === this._lastOpenedTab) { + this._lastOpenedTab = null; + } const groupIndex = this._data.findIndex((group) => group.tabs.includes(tab)); if (groupIndex < 0) { return; @@ -114,6 +120,18 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { this.removeTabFromGroup(tab, groupIndex, event.forUnsplit); } + /** + * @param {Event} event - The event that triggered the tab select. + * @description Handles the tab select event. + * @returns {void} + */ + onTabSelect(event) { + const previousTab = event.detail.previousTab; + if (previousTab) { + this._lastOpenedTab = previousTab; + } + } + /** * Removes a tab from a group. * @@ -160,7 +178,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { } draggedTab.container._finishMoveTogetherSelectedTabs(draggedTab); } - if (!draggedTab || this._canDrop || this._hasAnimated || this.fakeBrowser) { + if (!draggedTab || this._canDrop || this._hasAnimated || this.fakeBrowser || !this._lastOpenedTab) { return; } if (draggedTab.splitView) { @@ -170,7 +188,11 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { if (currentView?.tabs.length >= this.MAX_TABS) { return; } + const oldTab = this._lastOpenedTab; this._canDrop = true; + this._draggingTab = draggedTab; + gBrowser.selectedTab = oldTab; + draggedTab._visuallySelected = true; // wait some time before showing the split view this._showSplitViewTimeout = setTimeout(() => { this._hasAnimated = true; @@ -214,11 +236,12 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { } const panelsRect = gBrowser.tabbox.getBoundingClientRect(); // this event is fired even though we are still in the "allowed" area - console.log(event.target); if (event.target !== gBrowser.tabbox && event.target !== this.fakeBrowser) { return; } this._canDrop = false; + gBrowser.selectedTab = this._draggingTab; + this._draggingTab = null; if (this._showSplitViewTimeout) { clearTimeout(this._showSplitViewTimeout); } @@ -824,7 +847,8 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { * @param {string} gridType - The type of grid layout. */ splitTabs(tabs, gridType, initialIndex = 0) { - tabs = tabs.filter((t) => !t.hidden && !t.hasAttribute('zen-empty-tab')); + // TODO: Add support for splitting essential tabs + tabs = tabs.filter((t) => !t.hidden && !t.hasAttribute('zen-empty-tab') && !t.hasAttribute('zen-essential')); if (tabs.length < 2 || tabs.length > this.MAX_TABS) { return; } @@ -1416,6 +1440,8 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { gBrowser.tabbox.removeAttribute('style'); delete this._canDrop; delete this._hasAnimated; + gBrowser.selectedTab = this._draggingTab; + this._draggingTab = null; } } @@ -1426,7 +1452,11 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { * @returns {boolean} true if the tab was moved to the split view */ moveTabToSplitView(event, draggedTab) { + const canDrop = this._canDrop; this._mayabeRemoveFakeBrowser(); + if (!canDrop) { + return false; + } const dropTarget = document.elementFromPoint(event.clientX, event.clientY); const browser = dropTarget?.closest('browser'); @@ -1500,7 +1530,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { }, { type: 'spring', - bounce: 0.6, + bounce: 0.5, duration: 0.5, delay: 0.1, } diff --git a/src/browser/components/tabbrowser/content/tabs-js.patch b/src/browser/components/tabbrowser/content/tabs-js.patch index 978a13e6c..f4369f941 100644 --- a/src/browser/components/tabbrowser/content/tabs-js.patch +++ b/src/browser/components/tabbrowser/content/tabs-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js -index fa96568d366fd3608f9bd583fa793150bd815c8b..37644a42ac426c2a48e28056654eb654ffa660e4 100644 +index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de9d5b6d33 100644 --- a/browser/components/tabbrowser/content/tabs.js +++ b/browser/components/tabbrowser/content/tabs.js @@ -94,7 +94,7 @@ @@ -103,7 +103,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..37644a42ac426c2a48e28056654eb654 - this._finishMoveTogetherSelectedTabs(draggedTab); this._finishAnimateTabMove(); -+ if ((event.ctrlKey || event.metaKey) && !dt.mozUserCancelled && dt.dropEffect == "none" && !this._isCustomizing) { ++ if (!dt.mozUserCancelled && dt.dropEffect == "none" && !this._isCustomizing) { + const moved = gZenViewSplitter.moveTabToSplitView(event, draggedTab); + if (moved) { + delete draggedTab._dragData; From 2f8847b8fee8488c92c0d7544da86ad2797f60e4 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Mon, 3 Mar 2025 01:17:47 +0100 Subject: [PATCH 011/127] Add initial padding for animation in compact mode styles --- src/browser/base/content/zen-styles/zen-compact-mode.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/browser/base/content/zen-styles/zen-compact-mode.css b/src/browser/base/content/zen-styles/zen-compact-mode.css index 6fac7e8ad..fa6f2f835 100644 --- a/src/browser/base/content/zen-styles/zen-compact-mode.css +++ b/src/browser/base/content/zen-styles/zen-compact-mode.css @@ -38,6 +38,9 @@ --zen-toolbox-max-width: 64px !important; --zen-compact-float: var(--zen-element-separation); + /* Initial padding for when we are animating */ + padding: 0 0 0 var(--zen-toolbox-padding) !important; + &:not([animate='true']) { position: absolute; z-index: 10; From 7440f12117060bd1a834fb4384b9efa209f84780 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Mon, 3 Mar 2025 01:18:03 +0100 Subject: [PATCH 012/127] Made so split view can be rearranged without ctrl button event --- .../base/content/zen-styles/zen-decks.css | 2 +- .../base/zen-components/ZenViewSplitter.mjs | 33 ++++++++++--------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-decks.css b/src/browser/base/content/zen-styles/zen-decks.css index edb94880e..3ddb56a27 100644 --- a/src/browser/base/content/zen-styles/zen-decks.css +++ b/src/browser/base/content/zen-styles/zen-decks.css @@ -17,7 +17,7 @@ margin: 0; } #zen-splitview-dropzone { - border-radius: var(--zen-webview-border-radius, var(--zen-border-radius)); + border-radius: var(--zen-native-inner-radius); transition: inset ease-out 0.08s; display: none; background-color: color-mix(in srgb, var(--zen-colors-secondary) 30%, transparent 70%); diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index 645f34797..4e25b008e 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -167,7 +167,6 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { onBrowserDragOverToSplit(event) { var dt = event.dataTransfer; - const dragEffect = dt.dropEffect; var draggedTab; if (dt.mozTypesAt(0)[0] == TAB_DROP_TYPE) { // tab copy or move @@ -190,11 +189,11 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { } const oldTab = this._lastOpenedTab; this._canDrop = true; - this._draggingTab = draggedTab; - gBrowser.selectedTab = oldTab; - draggedTab._visuallySelected = true; // wait some time before showing the split view this._showSplitViewTimeout = setTimeout(() => { + this._draggingTab = draggedTab; + gBrowser.selectedTab = oldTab; + draggedTab._visuallySelected = true; this._hasAnimated = true; const panelsWidth = gBrowser.tabbox.getBoundingClientRect().width; const halfWidth = panelsWidth / 2; @@ -235,23 +234,22 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { return; } const panelsRect = gBrowser.tabbox.getBoundingClientRect(); - // this event is fired even though we are still in the "allowed" area if (event.target !== gBrowser.tabbox && event.target !== this.fakeBrowser) { return; } - this._canDrop = false; - gBrowser.selectedTab = this._draggingTab; - this._draggingTab = null; if (this._showSplitViewTimeout) { clearTimeout(this._showSplitViewTimeout); } - if (!this._hasAnimated) { + if (!this._hasAnimated || !this.fakeBrowser) { return; } setTimeout(() => { const panelsWidth = panelsRect.width; const halfWidth = panelsWidth / 2; const padding = Services.prefs.getIntPref('zen.theme.content-element-separation', 0); + if (!this.fakeBrowser) { + return; + } Promise.all([ gZenUIManager.motion.animate( gBrowser.tabbox, @@ -275,7 +273,10 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { } ), ]).then(() => { - this._mayabeRemoveFakeBrowser(); + this._canDrop = false; + gBrowser.selectedTab = this._draggingTab; + this._draggingTab = null; + this._maybeRemoveFakeBrowser(); }); }, 100); } @@ -837,7 +838,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { this.updateSplitView(tab); tab.linkedBrowser.docShellIsActive = true; } - this._mayabeRemoveFakeBrowser(); + this._maybeRemoveFakeBrowser(); } /** @@ -1433,13 +1434,12 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { } }; - _mayabeRemoveFakeBrowser() { + _maybeRemoveFakeBrowser() { + gBrowser.tabbox.removeAttribute('style'); if (this.fakeBrowser) { + delete this._hasAnimated; this.fakeBrowser.remove(); this.fakeBrowser = null; - gBrowser.tabbox.removeAttribute('style'); - delete this._canDrop; - delete this._hasAnimated; gBrowser.selectedTab = this._draggingTab; this._draggingTab = null; } @@ -1453,7 +1453,8 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { */ moveTabToSplitView(event, draggedTab) { const canDrop = this._canDrop; - this._mayabeRemoveFakeBrowser(); + this._maybeRemoveFakeBrowser(); + this._canDrop = false; if (!canDrop) { return false; } From e04cb679f96c3db39685b1a556dc89921f730916 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Mon, 3 Mar 2025 08:47:10 +0100 Subject: [PATCH 013/127] Fixed registring the empty tab as last selected on split views --- src/browser/base/zen-components/ZenViewSplitter.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index 4e25b008e..329093480 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -127,7 +127,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { */ onTabSelect(event) { const previousTab = event.detail.previousTab; - if (previousTab) { + if (previousTab && !previousTab.hasAttribute('zen-empty-tab')) { this._lastOpenedTab = previousTab; } } From 98668d53809328d85f1ed2881e50297082bc5a80 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Mon, 3 Mar 2025 10:56:10 +0100 Subject: [PATCH 014/127] Did more common fixes with the new split views implementation --- .../base/content/zen-styles/zen-decks.css | 5 ++ .../base/zen-components/ZenViewSplitter.mjs | 68 +++++++++++-------- 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-decks.css b/src/browser/base/content/zen-styles/zen-decks.css index 3ddb56a27..f94dd5899 100644 --- a/src/browser/base/content/zen-styles/zen-decks.css +++ b/src/browser/base/content/zen-styles/zen-decks.css @@ -277,4 +277,9 @@ opacity: 0; } } + + &.fade-out::after { + opacity: 0; + transition-delay: 0s; + } } diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index 329093480..f04e865e2 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -187,13 +187,18 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { if (currentView?.tabs.length >= this.MAX_TABS) { return; } + // only show if we are 1/4 of the way to the edge + const panelsRect = gBrowser.tabbox.getBoundingClientRect(); + const panelsWidth = panelsRect.width; + if (event.clientX > (panelsWidth / 4) * 3) { + return; + } const oldTab = this._lastOpenedTab; this._canDrop = true; // wait some time before showing the split view this._showSplitViewTimeout = setTimeout(() => { this._draggingTab = draggedTab; gBrowser.selectedTab = oldTab; - draggedTab._visuallySelected = true; this._hasAnimated = true; const panelsWidth = gBrowser.tabbox.getBoundingClientRect().width; const halfWidth = panelsWidth / 2; @@ -203,6 +208,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { this.fakeBrowser.id = 'zen-split-view-fake-browser'; gBrowser.tabbox.appendChild(this.fakeBrowser); this.fakeBrowser.style.setProperty('--zen-split-view-fake-icon', `url(${draggedTab.getAttribute('image')})`); + draggedTab._visuallySelected = true; Promise.all([ gZenUIManager.motion.animate( gBrowser.tabbox, @@ -234,7 +240,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { return; } const panelsRect = gBrowser.tabbox.getBoundingClientRect(); - if (event.target !== gBrowser.tabbox && event.target !== this.fakeBrowser) { + if (event.target.closest('#tabbrowser-tabbox') && event.target != this.fakeBrowser) { return; } if (this._showSplitViewTimeout) { @@ -250,34 +256,40 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { if (!this.fakeBrowser) { return; } - Promise.all([ - gZenUIManager.motion.animate( - gBrowser.tabbox, - { - paddingLeft: [`${halfWidth}px`, 0], - }, - { - duration: 0.15, - easing: 'ease-out', - } - ), - gZenUIManager.motion.animate( - this.fakeBrowser, - { - width: [`${halfWidth - padding * 2}px`, 0], - marginLeft: [`${-(halfWidth - padding)}px`, 0], - }, - { - duration: 0.15, - easing: 'ease-out', - } - ), - ]).then(() => { + this.fakeBrowser.classList.add('fade-out'); + gBrowser.selectedTab = this._draggingTab; + this._draggingTab = null; + try { + Promise.all([ + gZenUIManager.motion.animate( + gBrowser.tabbox, + { + paddingLeft: [`${halfWidth}px`, 0], + }, + { + duration: 0.15, + easing: 'ease-out', + } + ), + gZenUIManager.motion.animate( + this.fakeBrowser, + { + width: [`${halfWidth - padding * 2}px`, 0], + marginLeft: [`${-(halfWidth - padding)}px`, 0], + }, + { + duration: 0.15, + easing: 'ease-out', + } + ), + ]).then(() => { + this._canDrop = false; + this._maybeRemoveFakeBrowser(); + }); + } catch (e) { this._canDrop = false; - gBrowser.selectedTab = this._draggingTab; - this._draggingTab = null; this._maybeRemoveFakeBrowser(); - }); + } }, 100); } From b955be65f46d91e3110b480a68d9369a695ee0e8 Mon Sep 17 00:00:00 2001 From: Gabriel Fernandes Date: Mon, 3 Mar 2025 12:24:39 +0000 Subject: [PATCH 015/127] Feature: add martial arts uniform emoji --- src/browser/base/zen-components/ZenEmojies.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/base/zen-components/ZenEmojies.mjs b/src/browser/base/zen-components/ZenEmojies.mjs index e342c2909..a46451bf9 100644 --- a/src/browser/base/zen-components/ZenEmojies.mjs +++ b/src/browser/base/zen-components/ZenEmojies.mjs @@ -1 +1 @@ -function zenGlobalEmojis() { return [['⌚','watch','watch, clock, time, wristwatch'],['⌛','hourglass','hourglass done, time, sand, clock'],['⏪','rewind','arrow, blue, rewind, fast reverse button, left, back'],['⏫','arrow_double_up','increase, arrow, fast up button, blue, up'],['⏬','arrow_double_down','decrease, down, arrow, blue, fast down button'],['⏰','alarm_clock','alarm clock, clock, alarm, time, red'],['⏳','hourglass_flowing_sand','hourglass not done, time, sand, clock'],['⚽','soccer','sports, football, soccer ball, ball, soccer, soccer ball,'],['⚾','baseball','ball, baseball, sports'],['⛄','snowman','snowman, snowman without snow, christmas, holidays, snow'],['⛅','partly_sunny','sun, sun behind cloud, cloudy, sunny, weather'],['⛎','ophiuchus','zodiac, horoscope, Ophiuchus, purple'],['⛔','no_entry','sign, red, stop, no entry'],['⛪','church','church, building, religion, worship, faith, holy'],['⛲','fountain','fountain, water, garden'],['⛳','golf','sports, golf, flag in hole, flag'],['⛵','sailboat','vessel, vacation, sailing, sea, ship, sailboat, water, boat, travel, ocean'],['⛺','tent','camp, camping, outdoor, tent, camping, shelter, nature, vacation'],['⛽','fuelpump','oil, petrol, fuel pump, gas, red, gas station, fuel'],['✅','white_check_mark','approve, check, check mark, tick, check mark button, accept, yes, success, task'],['✊','fist','justice, raised fist, solidarity, empowerment, fist, strength'],['✋','raised_hand','hand, stop, halt, raised hand'],['✨','sparkles','sparkles, stars, shine, AI, magic, beauty, creativity'],['❌','x','cross mark, cross, wrong, no, red'],['❎','negative_squared_cross_mark','cross, no, green,, cross mark button'],['❓','question','curiosity, question mark, question, punctuation, red'],['⭐','star','star, five, achievement, favorite, yellow, gold, space, universe'],['⭕','o','hoop, hollow red circle, o, circle, red, round'],['🀄','mahjong','mahjong red dragon, china, game'],['🃏','black_joker','card, joker, game, deck, gamble'],['🆎','ab','red,, AB button (blood type)'],['🆑','cl','CL button, red'],['🆒','cool','cool, blue, COOL button'],['🆓','free','free, blue, FREE button'],['🆔','id','authentication, security, purple, identification, id, verification, ID button'],['🆕','new','new, blue, NEW button'],['🆖','ng','blue, ana ng, NG button, ng'],['🆗','ok','blue, okay, ok, OK button'],['🆘','sos','SOS button, emergency, danger, red, help, sos'],['🆙','up','UP! button, up, blue'],['🆚','vs','versus, duel, orange, contest, challenge, vs, battle, competition, VS button'],['🈁','koko','here, blue, japanese, Japanese here button'],['🈚','u7121','Japanese free of charge button, orange, japanese'],['🈯','u6307','Japanese reserved button, japanese, green'],['🈲','u7981','Japanese prohibited button, red, japanese'],['🈳','u7a7a','blue, Japanese vacancy button, japanese'],['🈴','u5408','Japanese passing grade button, red, japanese'],['🈵','u6e80','Japanese no vacancy button, red, japanese'],['🈶','u6709','Japanese not free of charge button, orange, japanese'],['🈸','u7533','Japanese application button, orange, japanese'],['🈹','u5272','Japanese discount button, red, japanese'],['🈺','u55b6','Japanese open for business button, orange, japanese'],['🉐','ideograph_advantage','Japanese bargain button, red, japanese'],['🉑','accept','Japanese acceptable button, orange, japanese'],['🌀','cyclone','cyclone, spiral, Zen, purple, swirl, storm'],['🌁','foggy','foggy, bridge, cloudy'],['🌂','closed_umbrella',', umbrella, purple, rain, closed umbrella, weather'],['🌃','night_with_stars','night, city, night with stars, scenery'],['🌄','sunrise_over_mountains','sunrise, sunrise over mountains, sun, sunset, nature, scenery'],['🌅','sunrise','sun, sunset, sunrise, scenery, nature'],['🌆','city_dusk','cityscape at dusk, city,, scenery'],['🌇','city_sunset','city, evening, sunset, scenery'],['🌈','rainbow','rainbow, pride, gay'],['🌉','bridge_at_night','night, bridge, bridge at night'],['🌊','ocean','water wave, tsunami, water, blue, ocean, art, sea, wave'],['🌋','volcano','volcano, eruption, lava, fire, geological'],['🌌','milky_way','science, milky way, galaxy, cosmos, stars, blue, nebula'],['🌍','earth_africa','africa, blue, planet, school, map, world, earth, globe, globe showing Europe-Africa, geography'],['🌎','earth_americas','blue, planet, america, school, map, globe showing Americas, world, earth, globe, geography'],['🌏','earth_asia','globe showing Asia-Australia, blue, asia, planet, school, map, world, earth, globe, australia, geography'],['🌐','globe_with_meridians','globe with meridians, blue, tech, internet, www, world, network, technology, web'],['🌑','new_moon','moon, lunar, purple, night, new moon, space, astronomy'],['🌒','waxing_crescent_moon','night, waxing crescent moon, astronomy, space, moon'],['🌓','first_quarter_moon','night, first quarter moon, astronomy, space, moon'],['🌔','waxing_gibbous_moon','night, waxing gibbous moon, astronomy, space, moon'],['🌕','full_moon','night, astronomy, full moon, space, yellow, moon'],['🌖','waning_gibbous_moon','night, astronomy, waning gibbous moon, space, moon'],['🌗','last_quarter_moon','night, astronomy, last quarter moon, space, moon'],['🌘','waning_crescent_moon','night, astronomy, waning crescent moon, space, moon'],['🌙','crescent_moon','night, astronomy, crescent moon, space, moon'],['🌚','new_moon_with_face','night, face, new moon face, astronomy, purple, space, moon'],['🌛','first_quarter_moon_with_face','night, face, astronomy, first quarter moon face, smile, space, yellow, moon'],['🌜','last_quarter_moon_with_face','night, face, astronomy, smile, last quarter moon face, space, yellow, moon'],['🌝','full_moon_with_face','night, face, full moon face, astronomy, smile, space, yellow, moon'],['🌞','sun_with_face','sun with face, night, face, astronomy, smile, space, yellow, moon'],['🌟','star2','sparkle, night, star, glowing star, yellow'],['🌠','stars','night, falling, star, cosmos, shooting star'],['🌭','hotdog','hotdog, hot dog, food'],['🌮','taco','taco, food'],['🌯','burrito','food, wrap, shawarma, burrito'],['🌰','chestnut','food, chestnut, onion'],['🌱','seedling',', green, plant, growth, seedling'],['🌲','evergreen_tree','holidays, christmas, green, evergreen tree, spruce, tree'],['🌳','deciduous_tree','oak, deciduous tree, environment, plant, nature, forest, tree, green'],['🌴','palm_tree','palm tree, vacation, palm, island, tree, beach'],['🌵','cactus','cactus, desert, green, nature, plant'],['🌷','tulip','flower, tulip, pink, nature, plant'],['🌸','cherry_blossom','pink, bloom, plant, nature, flower, sakura, cherry blossom'],['🌹','rose','flower, rose, red, nature, plant'],['🌺','hibiscus','hibiscus, pink, plant, nature, flower'],['🌻','sunflower','sunflower, nature, plant, flower, yellow'],['🌼','blossom','blossom, plant, nature, flower, white'],['🌽','corn','food, corn, ear of corn'],['🌾','ear_of_rice','food, sheaf of rice, wheat'],['🌿','herb','herb, plant'],['🍀','four_leaf_clover','lucky, four leaf clover, fortune, clover, green, plant'],['🍁','maple_leaf','maple leaf, autumn, plant, nature, leaf, fall, red, canada'],['🍂','fallen_leaf','brown, leaf, autumn, plant, nature, fall, dead leaves, fallen leaf'],['🍃','leaves','nature, green, leaf, leaf fluttering in wind, plant'],['🍄','mushroom','mushroom, nature, plant, fungi, toadstool'],['🍅','tomato','tomato, food, vegetable, red'],['🍆','eggplant','eggplant, food, vegetable, purple'],['🍇','grapes','food, fruit, grapes, grape, purple'],['🍈','melon','melon, fruit, food'],['🍉','watermelon','watermelon, fruit, food, red'],['🍊','tangerine','food, fruit, tangerine, orange'],['🍋','lemon','lemon, food, fruit, yellow'],['🍌','banana','banana, food, fruit, berry, yellow'],['🍍','pineapple','pineapple, food, fruit'],['🍎','apple','food, red apple, fruit, apple, school,, red'],['🍏','green_apple','food, fruit, green, apple, green apple'],['🍐','pear','pear, food, fruit, green'],['🍑','peach','peach, food, fruit'],['🍒','cherries','food, fruit, cherries, cherry, red'],['🍓','strawberry','strawberry, berry, fruit, food, red'],['🍔','hamburger','hamburger, america, food'],['🍕','pizza','pizza, food'],['🍖','meat_on_bone','food, meat on bone, ham'],['🍗','poultry_leg','chicken, poultry leg, food'],['🍘','rice_cracker','rice cracker, rice'],['🍙','rice_ball','onigiri, rice, rice ball, food'],['🍚','rice','food, rice, cooked rice'],['🍛','curry','food, rice, curry, curry rice'],['🍜','ramen','food, steaming bowl, ramen, noodles'],['🍝','spaghetti','food, pasta, spaghetti'],['🍞','bread','bread, food'],['🍟','fries','fries, french fries, french, food'],['🍠','sweet_potato','food, roasted, roasted sweet potato, sweet, potato'],['🍡','dango','dango, food'],['🍢','oden','oden, food'],['🍣','sushi','sushi, salmon, food'],['🍤','fried_shrimp','food, prawn, fried shrimp'],['🍥','fish_cake',', fish cake with swirl'],['🍦','icecream','desert, icecrean, soft ice cream, food'],['🍧','shaved_ice','desert, icecrean, shaved ice, food'],['🍨','ice_cream','desert, ice cream, icecrean, food'],['🍩','doughnut','desert, donut, doughnut, food'],['🍪','cookie','cookie, desert, food'],['🍫','chocolate_bar','desert, chocolate, chocolate bar, food'],['🍬','candy','candy, desert, food'],['🍭','lollipop','desert, candy, lollipop, food'],['🍮','custard','custard, food, dessert'],['🍯','honey_pot','food, honey, honey pot'],['🍰','cake','food, shortcake, cakedesert'],['🍱','bento','bento, rice, bento box, food'],['🍲','stew','food, soup, pot of food'],['🍳','cooking','food, cooking, omelette, egg'],['🍴','fork_and_knife','cutlery, food, fork and knife, fork, knife'],['🍵','tea','chai, food, drink, tea, teacup without handle'],['🍶','sake','sake, drink'],['🍷','wine_glass','food, wine glass, wine, drink'],['🍸','cocktail','food, glass, cocktail glass, drink, cocktail, martini'],['🍹','tropical_drink','drink, tropical drink, long island, food'],['🍺','beer','food, beer mug, drink, beer'],['🍻','beers','food, clinking beer mugs, drink, beer'],['🍼','baby_bottle','food, baby bottle, drink, baby, milk'],['🍾','champagne','drink, bottle with popping cork, champagne, food'],['🍿','popcorn','popcorn, food'],['🎀','ribbon','decoration, present, bow, ribbon, cute'],['🎁','gift','wrapped gift, present, christmas'],['🎂','birthday','birthday, birthday cake, cake'],['🎃','jack_o_lantern','scary, pumpkin, spooky, fall, orange, halloween, jack-o-lantern'],['🎄','christmas_tree','Christmas tree, tree, christmas, holidays'],['🎅','santa','santa, Santa Claus, christmas, holidays'],['🎆','fireworks','fireworks, party'],['🎇','sparkler','fireworks, sparkler, party'],['🎈','balloon','baloon, red, balloon'],['🎉','tada','confetti, party, party popper, celebration'],['🎊','confetti_ball','confetti, party, confetti ball, celebration'],['🎋','tanabata_tree','tanabata, tree, tanabata tree'],['🎌','crossed_flags',', crossed flags'],['🎍','bamboo','bamboo, pine decoration'],['🎎','dolls',', Japanese dolls'],['🎏','flags',', carp streamer'],['🎐','wind_chime',', wind chime'],['🎑','rice_scene',', moon viewing ceremony'],['🎒','school_satchel','school, backpack, bag'],['🎓','mortar_board','graduation, graduate, education, school, graduation cap, university'],['🎠','carousel_horse','park, carousel, carousel horse, pony'],['🎡','ferris_wheel','park, ferris, ferris wheel, wheel'],['🎢','roller_coaster','park, roller coaster, rollercoaster'],['🎣','fishing_pole_and_fish','fishing, fishing pole, fish, rod'],['🎤','microphone','microphone, speech, talk, singing'],['🎥','movie_camera','recording, movie camera, cinema, film, video, camera, content creation'],['🎦','cinema','camera, blue, recording, video, film, cinema'],['🎧','headphones','music, headphone, headphones, audio'],['🎨','art','colors, artist palette, creativity, design, painting, art, inspiration'],['🎩','tophat','hat, top hat, magic'],['🎪','circus_tent','circus, circus tent'],['🎫','ticket','ticket'],['🎬','clapper','video editing, media, video, clapper board, audiovisual'],['🎭','performing_arts','theater, performing arts, drama, masks'],['🎮','video_game','xbox, ps4, gaming, video game, playstation'],['🎯','dart','direct hit, goal, target, task'],['🎰','slot_machine','slot, casino, slot machine, games, gambling'],['🎱','8ball','billiard, games, ball, 8, eight, pool 8 ball'],['🎲','game_die','dice, luck, games, one, 1, game die'],['🎳','bowling','bowling, games, games'],['🎴','flower_playing_cards','play, card, flower playing cards'],['🎵','musical_note','note, musical note, song, music'],['🎶','notes','note, song, music, musical notes'],['🎷','saxophone','instrument, song, music, sax, saxophone'],['🎸','guitar','music, guitar, instrument, electric, song'],['🎹','musical_keyboard','instrument, song, music, piano, musical keyboard'],['🎺','trumpet','music, trumpet, instrument, song'],['🎻','violin','music, instrument, violin, sound'],['🎼','musical_score','musical score, sound, music'],['🎽','running_shirt_with_sash','clothes, running shirt, vest'],['🎾','tennis','tennis, sport'],['🎿','ski','scating, sport, skis'],['🏀','basketball','basketball, sport, orange'],['🏁','checkered_flag','finish, sport, chequered flag, race'],['🏂','snowboarder','snowboarder, snowboard, sport, snow'],['🏃','person_running','person running, sport, running'],['🏄','person_surfing','person surfing, surfing, sport'],['🏅','medal','gold, win, medal, sports medal'],['🏆','trophy','trophy, win, gold'],['🏇','horse_racing','horse racing, horse, sport, racing'],['🏈','football','american football, brown, football, sport'],['🏉','rugby_football','rugby football, football, sport'],['🏊','person_swimming','sport, swimming, person swimming'],['🏏','cricket_game','baseball, sport, cricket, cricket game'],['🏐','volleyball','white, football, volleyball, sport'],['🏑','field_hockey','hockey, field hockey, sport, field'],['🏒','hockey','hockey, ice hockey, sport'],['🏓','ping_pong','ping pong, tennis, sport'],['🏠','house','home, house, building'],['🏡','house_with_garden','building, house with garden, home, house'],['🏢','office','office building, work, building, office'],['🏣','post_office','building, post, office, Japanese post office'],['🏤','european_post_office','post office, building, post, office'],['🏥','hospital','hospital, building, health'],['🏦','bank','bank, money, building'],['🏧','atm','atm, ATM sign, blue'],['🏨','hotel','hotel, building'],['🏩','love_hotel','love, building, hotel, love hotel'],['🏪','convenience_store','store, building, shop, groceries, convenience store, convenience'],['🏫','school','school, building'],['🏬','department_store','store, building, department store'],['🏭','factory','factory, work, building'],['🏮','izakaya_lantern','lamp, red paper lantern, light'],['🏯','japanese_castle','building, Japanese castle, temple, castle, fortress'],['🏰','european_castle','temple, castle, fortress, building'],['🏴','flag_black','black flag, flag, black'],['🏸','badminton','badminton, racket, sport'],['🏹','bow_and_arrow','archery, bow and arrow, sport'],['🏺','amphora','amphora, vase'],['🐀','rat','animal, rat'],['🐁','mouse2','animal, mouse'],['🐂','ox','animal, ox'],['🐃','water_buffalo',', water buffalo'],['🐄','cow2','animal, cow'],['🐅','tiger2','animal, tiger'],['🐆','leopard','animal, leopard'],['🐇','rabbit2','animal, rabbit, bunny, hair'],['🐈','cat2','animal, cat'],['🐉','dragon','animal, dragon'],['🐊','crocodile','alagator, animal, crocodile, green'],['🐋','whale2','animal, whale, blue'],['🐌','snail','animal, snail'],['🐍','snake','animal, snake'],['🐎','racehorse','animal, horse'],['🐏','ram','animal, ram'],['🐐','goat','animal, goat'],['🐑','sheep','animal, ewe'],['🐒','monkey','animal, monkey'],['🐓','rooster','animal, rooster'],['🐔','chicken','chicken, animal'],['🐕','dog2','animal, dog'],['🐖','pig2','animal, pig'],['🐗','boar','animal, boar'],['🐘','elephant','animal, elephant'],['🐙','octopus','animal, octopus'],['🐚','shell','spiral shell, seashell, sea, beach, ocean'],['🐛','bug','animal, insect, bug'],['🐜','ant','animal, insect, ant, bug'],['🐝','bee','animal, insect, bug, honeybee'],['🐞','beetle','animal, insect, bug, lady beetle'],['🐟','fish','animal, fish'],['🐠','tropical_fish','tropical fish, animal'],['🐡','blowfish','animal, blowfish'],['🐢','turtle','animal, turtle, green'],['🐣','hatching_chick','hatching chick, animal'],['🐤','baby_chick','animal, baby chick'],['🐥','hatched_chick','animal, front-facing baby chick'],['🐦','bird','animal, bird'],['🐧','penguin','linux, animal, penguin'],['🐨','koala','animal, koala'],['🐩','poodle','animal, poodle'],['🐪','dromedary_camel','animal, camel'],['🐫','camel','animal, two-hump camel'],['🐬','dolphin','animal, dolphin'],['🐭','mouse','animal, mouse face, face'],['🐮','cow','animal, face, cow face'],['🐯','tiger','tiger face, animal, face'],['🐰','rabbit','animal, cute, rabbit face'],['🐱','cat','animal, cat face, face, cute'],['🐲','dragon_face','animal, dragon face'],['🐳','whale','animal, spouting whale'],['🐴','horse','animal, face, horse face'],['🐵','monkey_face','monkey face, animal, face'],['🐶','dog','animal, face, dog face'],['🐷','pig','animal, face, pig face'],['🐸','frog','frog, animal, face'],['🐹','hamster','animal, face, hamster'],['🐺','wolf','animal, face, wolf'],['🐻','bear','animal, face, bear'],['🐼','panda_face','animal, panda'],['🐽','pig_nose','animal, pig nose, nose'],['🐾','feet','animal, tracks, paw prints'],['👀','eyes','looking, eyes'],['👂','ear','listen, sound, ear'],['👃','nose','nose, smell'],['👄','lips','mouth'],['👅','tongue','tongue, silly, mouth'],['👆','point_up_2',', backhand index pointing up'],['👇','point_down',', backhand index pointing down'],['👈','point_left',', backhand index pointing left'],['👉','point_right',', backhand index pointing right'],['👊','punch',', oncoming fist'],['👋','wave',', waving hand'],['👌','ok_hand',', OK hand'],['👍','thumbsup',', thumbs up'],['👎','thumbsdown',', thumbs down'],['👏','clap',', clapping hands'],['👐','open_hands',', open hands'],['👑','crown',', crown'],['👒','womans_hat',', woman’s hat'],['👓','eyeglasses',', glasses'],['👔','necktie',', necktie'],['👕','shirt',', t-shirt'],['👖','jeans',', jeans'],['👗','dress',', dress'],['👘','kimono',', kimono'],['👙','bikini',', bikini'],['👚','womans_clothes',', woman’s clothes'],['👛','purse',', purse'],['👜','handbag',', handbag'],['👝','pouch',', clutch bag'],['👞','mans_shoe',', man’s shoe'],['👟','athletic_shoe',', running shoe'],['👠','high_heel',', high-heeled shoe'],['👡','sandal',', woman’s sandal'],['👢','boot',', woman’s boot'],['👣','footprints',', footprints'],['👤','bust_in_silhouette',', bust in silhouette'],['👥','busts_in_silhouette',', busts in silhouette'],['👦','boy',', boy'],['👧','girl',', girl'],['👨','man',', man'],['👩','woman',', woman'],['👪','family',', family'],['👫','couple',', woman and man holding hands'],['👬','two_men_holding_hands',', men holding hands'],['👭','two_women_holding_hands',', women holding hands'],['👮','police_officer',', police officer'],['👯','people_with_bunny_ears_partying',', people with bunny ears'],['👰','bride_with_veil',', bride with veil'],['👱','blond_haired_person',', person: blond hair'],['👲','man_with_chinese_cap',', man with skullcap'],['👳','person_wearing_turban',', person wearing turban'],['👴','older_man',', old man'],['👵','older_woman',', old woman'],['👶','baby',', baby'],['👷','construction_worker',', construction worker'],['👸','princess',', princess'],['👹','japanese_ogre',', ogre'],['👺','japanese_goblin',', goblin'],['👻','ghost','ghost, halloween'],['👼','angel',', baby angel'],['👽','alien',', alien'],['👾','space_invader',', alien monster'],['👿','imp',', angry face with horns'],['💀','skull','spooky, skull, horror, bones'],['💁','person_tipping_hand','person tipping hand, questions'],['💂','guard',', guard'],['💃','dancer',', woman dancing'],['💄','lipstick','makeup, lipstick'],['💅','nail_care','beauty, nail polish, makeup'],['💆','person_getting_massage',', person getting massage'],['💇','person_getting_haircut',', person getting haircut'],['💈','barber',', barber pole'],['💉','syringe',', syringe'],['💊','pill',', pill'],['💋','kiss',', kiss mark'],['💌','love_letter',', love letter'],['💍','ring',', ring'],['💎','gem',', gem stone'],['💏','couplekiss',', kiss'],['💐','bouquet',', bouquet'],['💑','couple_with_heart',', couple with heart'],['💒','wedding',', wedding'],['💓','heartbeat',', beating heart'],['💔','broken_heart',', broken heart'],['💕','two_hearts',', two hearts'],['💖','sparkling_heart',', sparkling heart'],['💗','heartpulse',', growing heart'],['💘','cupid',', heart with arrow'],['💙','blue_heart',', blue heart'],['💚','green_heart',', green heart'],['💛','yellow_heart',', yellow heart'],['💜','purple_heart',', purple heart'],['💝','gift_heart',', heart with ribbon'],['💞','revolving_hearts',', revolving hearts'],['💟','heart_decoration',', heart decoration'],['💠','diamond_shape_with_a_dot_inside',', diamond with a dot'],['💡','bulb',', light bulb'],['💢','anger',', anger symbol'],['💣','bomb',', bomb'],['💤','zzz',', zzz'],['💥','boom',', collision'],['💦','sweat_drops',', sweat droplets'],['💧','droplet',', droplet'],['💨','dash',', dashing away'],['💩','poop',', pile of poo'],['💪','muscle',', flexed biceps'],['💫','dizzy',', dizzy'],['💬','speech_balloon',', speech balloon'],['💭','thought_balloon',', thought balloon'],['💮','white_flower',', white flower'],['💯','100',', hundred points'],['💰','moneybag',', money bag'],['💱','currency_exchange',', currency exchange'],['💲','heavy_dollar_sign',', heavy dollar sign'],['💳','credit_card',', credit card'],['💴','yen',', yen banknote'],['💵','dollar',', dollar banknote'],['💶','euro',', euro banknote'],['💷','pound',', pound banknote'],['💸','money_with_wings',', money with wings'],['💹','chart',', chart increasing with yen'],['💺','seat',', seat'],['💻','computer',', laptop'],['💼','briefcase',', briefcase'],['💽','minidisc',', computer disk'],['💾','floppy_disk',', floppy disk'],['💿','cd',', optical disk'],['📀','dvd',', dvd'],['📁','file_folder',', file folder'],['📂','open_file_folder',', open file folder'],['📃','page_with_curl',', page with curl'],['📄','page_facing_up',', page facing up'],['📅','date',', calendar'],['📆','calendar',', tear-off calendar'],['📇','card_index',', card index'],['📈','chart_with_upwards_trend',', chart increasing'],['📉','chart_with_downwards_trend',', chart decreasing'],['📊','bar_chart',', bar chart'],['📋','clipboard',', clipboard'],['📌','pushpin',', pushpin'],['📍','round_pushpin',', round pushpin'],['📎','paperclip',', paperclip'],['📏','straight_ruler',', straight ruler'],['📐','triangular_ruler',', triangular ruler'],['📑','bookmark_tabs',', bookmark tabs'],['📒','ledger',', ledger'],['📓','notebook',', notebook'],['📔','notebook_with_decorative_cover',', notebook with decorative cover'],['📕','closed_book',', closed book'],['📖','book',', open book'],['📗','green_book',', green book'],['📘','blue_book',', blue book'],['📙','orange_book',', orange book'],['📚','books','books, study, school'],['📛','name_badge',', name badge'],['📜','scroll',', scroll'],['📝','pencil','pencil, memo, note, school, study'],['📞','telephone_receiver','call, telephone receiver, phone'],['📟','pager',', pager'],['📠','fax',', fax machine'],['📡','satellite',', satellite antenna'],['📢','loudspeaker',', loudspeaker'],['📣','mega',', megaphone'],['📤','outbox_tray',', outbox tray'],['📥','inbox_tray',', inbox tray'],['📦','package',', package'],['📧','e-mail','mail, e-mail'],['📨','incoming_envelope','mail, incoming envelope'],['📩','envelope_with_arrow','mail, envelope with arrow'],['📪','mailbox_closed','closed mailbox with lowered flag, mail'],['📫','mailbox','mail, closed mailbox with raised flag'],['📬','mailbox_with_mail','mail, open mailbox with raised flag'],['📭','mailbox_with_no_mail','mail, open mailbox with lowered flag'],['📮','postbox',', postbox'],['📯','postal_horn',', postal horn'],['📰','newspaper',', newspaper'],['📱','iphone',', mobile phone'],['📲','calling',', mobile phone with arrow'],['📳','vibration_mode',', vibration mode'],['📴','mobile_phone_off',', mobile phone off'],['📵','no_mobile_phones',', no mobile phones'],['📶','signal_strength',', antenna bars'],['📷','camera','photo, photography, camera'],['📸','camera_with_flash','camera with flash, photo, photography'],['📹','video_camera',', video camera'],['📺','tv',', television'],['📻','radio',', radio'],['📼','vhs',', videocassette'],['📿','prayer_beads',', prayer beads'],['🔀','twisted_rightwards_arrows',', shuffle tracks button'],['🔁','repeat',', repeat button'],['🔂','repeat_one',', repeat single button'],['🔃','arrows_clockwise',', clockwise vertical arrows'],['🔄','arrows_counterclockwise',', counterclockwise arrows button'],['🔅','low_brightness',', dim button'],['🔆','high_brightness',', bright button'],['🔇','mute',', muted speaker'],['🔈','speaker',', speaker low volume'],['🔉','sound',', speaker medium volume'],['🔊','loud_sound',', speaker high volume'],['🔋','battery',', battery'],['🔌','electric_plug',', electric plug'],['🔍','mag','magnifying glass tilted left, search'],['🔎','mag_right','search, magnifying glass tilted right'],['🔏','lock_with_ink_pen',', locked with pen'],['🔐','closed_lock_with_key',', locked with key'],['🔑','key',', key'],['🔒','lock',', locked'],['🔓','unlock',', unlocked'],['🔔','bell',', bell'],['🔕','no_bell',', bell with slash'],['🔖','bookmark',', bookmark'],['🔗','link',', link'],['🔘','radio_button',', radio button'],['🔙','back',', BACK arrow'],['🔚','end',', END arrow'],['🔛','on',', ON! arrow'],['🔜','soon',', SOON arrow'],['🔝','top',', TOP arrow'],['🔞','underage',', no one under eighteen'],['🔟','keycap_ten',', keycap: 10'],['🔠','capital_abcd',', input latin uppercase'],['🔡','abcd',', input latin lowercase'],['🔢','1234',', input numbers'],['🔣','symbols',', input symbols'],['🔤','abc',', input latin letters'],['🔥','fire',', fire'],['🔦','flashlight',', flashlight'],['🔧','wrench',', wrench'],['🔨','hammer',', hammer'],['🔩','nut_and_bolt',', nut and bolt'],['🔪','knife',', kitchen knife'],['🔫','gun',', pistol'],['🔬','microscope',', microscope'],['🔭','telescope',', telescope'],['🔮','crystal_ball',', crystal ball'],['🔯','six_pointed_star',', dotted six-pointed star'],['🔰','beginner',', Japanese symbol for beginner'],['🔱','trident',', trident emblem'],['🔲','black_square_button',', black square button'],['🔳','white_square_button',', white square button'],['🔴','red_circle',', red circle'],['🔵','blue_circle',', blue circle'],['🔶','large_orange_diamond',', large orange diamond'],['🔷','large_blue_diamond',', large blue diamond'],['🔸','small_orange_diamond',', small orange diamond'],['🔹','small_blue_diamond',', small blue diamond'],['🔺','small_red_triangle',', red triangle pointed up'],['🔻','small_red_triangle_down',', red triangle pointed down'],['🔼','arrow_up_small',', upwards button'],['🔽','arrow_down_small',', downwards button'],['🕋','kaaba',', kaaba'],['🕌','mosque',', mosque'],['🕍','synagogue',', synagogue'],['🕎','menorah',', menorah'],['🕐','clock1',', one o’clock'],['🕑','clock2',', two o’clock'],['🕒','clock3',', three o’clock'],['🕓','clock4',', four o’clock'],['🕔','clock5',', five o’clock'],['🕕','clock6',', six o’clock'],['🕖','clock7',', seven o’clock'],['🕗','clock8',', eight o’clock'],['🕘','clock9',', nine o’clock'],['🕙','clock10',', ten o’clock'],['🕚','clock11',', eleven o’clock'],['🕛','clock12',', twelve o’clock'],['🕜','clock130',', one-thirty'],['🕝','clock230',', two-thirty'],['🕞','clock330',', three-thirty'],['🕟','clock430',', four-thirty'],['🕠','clock530',', five-thirty'],['🕡','clock630',', six-thirty'],['🕢','clock730',', seven-thirty'],['🕣','clock830',', eight-thirty'],['🕤','clock930',', nine-thirty'],['🕥','clock1030',', ten-thirty'],['🕦','clock1130',', eleven-thirty'],['🕧','clock1230',', twelve-thirty'],['🖕','middle_finger',', middle finger'],['🖖','vulcan',', vulcan salute'],['🗻','mount_fuji',', mount fuji'],['🗼','tokyo_tower',', Tokyo tower'],['🗽','statue_of_liberty',', Statue of Liberty'],['🗾','japan',', map of Japan'],['🗿','moyai',', moai'],['😀','grinning',', grinning face'],['😁','grin',', beaming face with smiling eyes'],['😂','joy',', face with tears of joy'],['😃','smiley',', grinning face with big eyes'],['😄','smile',', grinning face with smiling eyes'],['😅','sweat_smile',', grinning face with sweat'],['😆','laughing',', grinning squinting face'],['😇','innocent',', smiling face with halo'],['😈','smiling_imp',', smiling face with horns'],['😉','wink',', winking face'],['😊','blush',', smiling face with smiling eyes'],['😋','yum',', face savoring food'],['😌','relieved',', relieved face'],['😍','heart_eyes',', smiling face with heart-eyes'],['😎','sunglasses',', smiling face with sunglasses'],['😏','smirk',', smirking face'],['😐','neutral_face',', neutral face'],['😑','expressionless',', expressionless face'],['😒','unamused',', unamused face'],['😓','sweat',', downcast face with sweat'],['😔','pensive',', pensive face'],['😕','confused',', confused face'],['😖','confounded',', confounded face'],['😗','kissing',', kissing face'],['😘','kissing_heart',', face blowing a kiss'],['😙','kissing_smiling_eyes',', kissing face with smiling eyes'],['😚','kissing_closed_eyes',', kissing face with closed eyes'],['😛','stuck_out_tongue',', face with tongue'],['😜','stuck_out_tongue_winking_eye',', winking face with tongue'],['😝','stuck_out_tongue_closed_eyes',', squinting face with tongue'],['😞','disappointed',', disappointed face'],['😟','worried',', worried face'],['😠','angry',', angry face'],['😡','rage',', pouting face'],['😢','cry',', crying face'],['😣','persevere',', persevering face'],['😤','triumph',', face with steam from nose'],['😥','disappointed_relieved',', sad but relieved face'],['😦','frowning',', frowning face with open mouth'],['😧','anguished',', anguished face'],['😨','fearful',', fearful face'],['😩','weary',', weary face'],['😪','sleepy',', sleepy face'],['😫','tired_face',', tired face'],['😬','grimacing',', grimacing face'],['😭','sob',', loudly crying face'],['😮','open_mouth',', face with open mouth'],['😯','hushed',', hushed face'],['😰','cold_sweat',', anxious face with sweat'],['😱','scream',', face screaming in fear'],['😲','astonished',', astonished face'],['😳','flushed',', flushed face'],['😴','sleeping',', sleeping face'],['😵','dizzy_face',', dizzy face'],['😶','no_mouth',', face without mouth'],['😷','mask',', face with medical mask'],['😸','smile_cat',', grinning cat with smiling eyes'],['😹','joy_cat',', cat with tears of joy'],['😺','smiley_cat','grinning cat, kitty'],['😻','heart_eyes_cat',', smiling cat with heart-eyes'],['😼','smirk_cat',', cat with wry smile'],['😽','kissing_cat',', kissing cat'],['😾','pouting_cat',', pouting cat'],['😿','crying_cat_face',', crying cat'],['🙀','scream_cat',', weary cat'],['🙁','slight_frown',', slightly frowning face'],['🙂','slight_smile',', slightly smiling face'],['🙃','upside_down',', upside-down face'],['🙄','rolling_eyes',', face with rolling eyes'],['🙅','person_gesturing_no',', person gesturing NO'],['🙆','person_gesturing_ok',', person gesturing OK'],['🙇','person_bowing',', person bowing'],['🙈','see_no_evil',', see-no-evil monkey'],['🙉','hear_no_evil',', hear-no-evil monkey'],['🙊','speak_no_evil',', speak-no-evil monkey'],['🙋','person_raising_hand',', person raising hand'],['🙌','raised_hands',', raising hands'],['🙍','person_frowning',', person frowning'],['🙎','person_pouting',', person pouting'],['🙏','pray',', folded hands'],['🚀','rocket',', rocket'],['🚁','helicopter',', helicopter'],['🚂','steam_locomotive',', locomotive'],['🚃','railway_car',', railway car'],['🚄','bullettrain_side',', high-speed train'],['🚅','bullettrain_front',', bullet train'],['🚆','train2',', train'],['🚇','metro',', metro'],['🚈','light_rail',', light rail'],['🚉','station',', station'],['🚊','tram',', tram'],['🚋','train',', tram car'],['🚌','bus',', bus'],['🚍','oncoming_bus',', oncoming bus'],['🚎','trolleybus',', trolleybus'],['🚏','busstop',', bus stop'],['🚐','minibus',', minibus'],['🚑','ambulance',', ambulance'],['🚒','fire_engine',', fire engine'],['🚓','police_car',', police car'],['🚔','oncoming_police_car',', oncoming police car'],['🚕','taxi',', taxi'],['🚖','oncoming_taxi',', oncoming taxi'],['🚗','red_car',', automobile'],['🚘','oncoming_automobile',', oncoming automobile'],['🚙','blue_car',', sport utility vehicle'],['🚚','truck',', delivery truck'],['🚛','articulated_lorry',', articulated lorry'],['🚜','tractor',', tractor'],['🚝','monorail',', monorail'],['🚞','mountain_railway',', mountain railway'],['🚟','suspension_railway',', suspension railway'],['🚠','mountain_cableway',', mountain cableway'],['🚡','aerial_tramway',', aerial tramway'],['🚢','ship',', ship'],['🚣','person_rowing_boat',', person rowing boat'],['🚤','speedboat',', speedboat'],['🚥','traffic_light',', horizontal traffic light'],['🚦','vertical_traffic_light',', vertical traffic light'],['🚧','construction',', construction'],['🚨','rotating_light',', police car light'],['🚩','triangular_flag_on_post',', triangular flag'],['🚪','door',', door'],['🚫','no_entry_sign',', prohibited'],['🚬','smoking',', cigarette'],['🚭','no_smoking',', no smoking'],['🚮','put_litter_in_its_place',', litter in bin sign'],['🚯','do_not_litter',', no littering'],['🚰','potable_water',', potable water'],['🚱','non-potable_water',', non-potable water'],['🚲','bike',', bicycle'],['🚳','no_bicycles',', no bicycles'],['🚴','person_biking',', person biking'],['🚵','person_mountain_biking',', person mountain biking'],['🚶','person_walking',', person walking'],['🚷','no_pedestrians',', no pedestrians'],['🚸','children_crossing',', children crossing'],['🚹','mens',', men’s room'],['🚺','womens',', women’s room'],['🚻','restroom',', restroom'],['🚼','baby_symbol',', baby symbol'],['🚽','toilet',', toilet'],['🚾','wc',', water closet'],['🚿','shower',', shower'],['🛀','bath',', person taking bath'],['🛁','bathtub',', bathtub'],['🛂','passport_control',', passport control'],['🛃','customs',', customs'],['🛄','baggage_claim',', baggage claim'],['🛅','left_luggage',', left luggage'],['🛌','sleeping_accommodation',', person in bed'],['🛐','place_of_worship',', place of worship'],['🛫','airplane_departure',', airplane departure'],['🛬','airplane_arriving',', airplane arrival'],['🤐','zipper_mouth',', zipper-mouth face'],['🤑','money_mouth',', money-mouth face'],['🤒','thermometer_face',', face with thermometer'],['🤓','nerd',', nerd face'],['🤔','thinking',', thinking face'],['🤕','head_bandage',', face with head-bandage'],['🤖','robot','robot, electronics, AI, artificial intelligence, tech, technology'],['🤗','hugging','hugging face, AI, artificial intelligence'],['🤘','metal','hand, rock, sign of the horns'],['🦀','crab','sea creature, crab, animal, sea, seafood'],['🦁','lion_face','animal, lion'],['🦂','scorpion','animal, scorpion'],['🦃','turkey','turkey, bird,, thanksgiving'],['🦄','unicorn','magic, fantasy, rainbow, unicorn'],['🧀','cheese','food, mouse, cheese wedge'],['🇦🇨','flag_ac','flags, flag: Ascension Island, flag'],['🇦🇩','flag_ad','flag: Andorra, flags, flag'],['🇦🇪','flag_ae','flags, flag: United Arab Emirates, flag'],['🇦🇫','flag_af','flags, flag, flag: Afghanistan'],['🇦🇬','flag_ag','flag: Antigua & Barbuda, flags, flag'],['🇦🇮','flag_ai','flags, flag, flag: Anguilla'],['🇦🇱','flag_al','flag: Albania, flags, flag'],['🇦🇲','flag_am','flags, flag: Armenia, flag'],['🇦🇴','flag_ao','flags, flag, flag: Angola'],['🇦🇶','flag_aq','flag: Antarctica, flags, flag'],['🇦🇷','flag_ar','flags, flag: Argentina, flag'],['🇦🇸','flag_as','flags, flag: American Samoa, flag'],['🇦🇹','flag_at','flags, flag, flag: Austria'],['🇦🇺','flag_au','flags, flag, flag: Australia'],['🇦🇼','flag_aw','flag: Aruba, flags, flag'],['🇦🇽','flag_ax','flag: Åland Islands, flags, flag'],['🇦🇿','flag_az','flags, flag, flag: Azerbaijan'],['🇧🇦','flag_ba','flag: Bosnia & Herzegovina, flags, flag'],['🇧🇧','flag_bb','flag: Barbados, flags, flag'],['🇧🇩','flag_bd','flags, flag, flag: Bangladesh'],['🇧🇪','flag_be','flags, flag, flag: Belgium'],['🇧🇫','flag_bf','flags, flag: Burkina Faso, flag'],['🇧🇬','flag_bg','flag: Bulgaria, flags, flag'],['🇧🇭','flag_bh','flags, flag: Bahrain, flag'],['🇧🇮','flag_bi','flag: Burundi, flags, flag'],['🇧🇯','flag_bj','flag: Benin, flags, flag'],['🇧🇱','flag_bl','flags, flag: St. Barthélemy, flag'],['🇧🇲','flag_bm','flags, flag: Bermuda, flag'],['🇧🇳','flag_bn','flags, flag: Brunei, flag'],['🇧🇴','flag_bo','flag: Bolivia, flags, flag'],['🇧🇶','flag_bq','flags, flag: Caribbean Netherlands, flag'],['🇧🇷','flag_br','flag: Brazil, flags, flag'],['🇧🇸','flag_bs','flag: Bahamas, flags, flag'],['🇧🇹','flag_bt','flags, flag: Bhutan, flag'],['🇧🇻','flag_bv','flag: Bouvet Island, flags, flag'],['🇧🇼','flag_bw','flags, flag, flag: Botswana'],['🇧🇾','flag_by','flags, flag, flag: Belarus'],['🇧🇿','flag_bz','flag: Belize, flags, flag'],['🇨🇦','flag_ca','flag: Canada, flags, flag'],['🇨🇨','flag_cc','flags, flag: Cocos (Keeling) Islands, flag'],['🇨🇩','flag_cd','flag: Congo - Kinshasa, flags, flag'],['🇨🇫','flag_cf','flag: Central African Republic, flags, flag'],['🇨🇬','flag_cg','flags, flag: Congo - Brazzaville, flag'],['🇨🇭','flag_ch','flags, flag: Switzerland, flag'],['🇨🇮','flag_ci','flags, flag: Côte d’Ivoire, flag'],['🇨🇰','flag_ck','flag: Cook Islands, flags, flag'],['🇨🇱','flag_cl','flag: Chile, flags, flag'],['🇨🇲','flag_cm','flag: Cameroon, flags, flag'],['🇨🇳','flag_cn','flags, flag, flag: China'],['🇨🇴','flag_co','flags, flag: Colombia, flag'],['🇨🇵','flag_cp','flags, flag, flag: Clipperton Island'],['🇨🇷','flag_cr','flag: Costa Rica, flags, flag'],['🇨🇺','flag_cu','flag: Cuba, flags, flag'],['🇨🇻','flag_cv','flags, flag: Cape Verde, flag'],['🇨🇼','flag_cw','flag: Curaçao, flags, flag'],['🇨🇽','flag_cx','flags, flag: Christmas Island, flag'],['🇨🇾','flag_cy','flags, flag: Cyprus, flag'],['🇨🇿','flag_cz','flags, flag, flag: Czechia'],['🇩🇪','flag_de','flags, flag, flag: Germany'],['🇩🇬','flag_dg','flag: Diego Garcia, flags, flag'],['🇩🇯','flag_dj','flag: Djibouti, flags, flag'],['🇩🇰','flag_dk','flags, flag, flag: Denmark'],['🇩🇲','flag_dm','flags, flag: Dominica, flag'],['🇩🇴','flag_do','flags, flag: Dominican Republic, flag'],['🇩🇿','flag_dz','flag: Algeria, flags, flag'],['🇪🇦','flag_ea','flags, flag: Ceuta & Melilla, flag'],['🇪🇨','flag_ec','flag: Ecuador, flags, flag'],['🇪🇪','flag_ee','flags, flag, flag: Estonia'],['🇪🇬','flag_eg','flag: Egypt, flags, flag'],['🇪🇭','flag_eh','flags, flag: Western Sahara, flag'],['🇪🇷','flag_er','flags, flag, flag: Eritrea'],['🇪🇸','flag_es','flags, flag: Spain, flag'],['🇪🇹','flag_et','flags, flag: Ethiopia, flag'],['🇪🇺','flag_eu','flags, flag: European Union, flag'],['🇫🇮','flag_fi','flag: Finland, flags, flag'],['🇫🇯','flag_fj','flags, flag, flag: Fiji'],['🇫🇰','flag_fk','flags, flag: Falkland Islands, flag'],['🇫🇲','flag_fm','flags, flag: Micronesia, flag'],['🇫🇴','flag_fo','flags, flag: Faroe Islands, flag'],['🇫🇷','flag_fr','flag: France, flags, flag'],['🇬🇦','flag_ga','flags, flag: Gabon, flag'],['🇬🇧','flag_gb','flag: United Kingdom, flags, flag'],['🇬🇩','flag_gd','flag: Grenada, flags, flag'],['🇬🇪','flag_ge','flags, flag, flag: Georgia'],['🇬🇫','flag_gf','flags, flag, flag: French Guiana'],['🇬🇬','flag_gg','flag: Guernsey, flags, flag'],['🇬🇭','flag_gh','flag: Ghana, flags, flag'],['🇬🇮','flag_gi','flags, flag, flag: Gibraltar'],['🇬🇱','flag_gl','flags, flag: Greenland, flag'],['🇬🇲','flag_gm','flag: Gambia, flags, flag'],['🇬🇳','flag_gn','flags, flag: Guinea, flag'],['🇬🇵','flag_gp','flags, flag: Guadeloupe, flag'],['🇬🇶','flag_gq','flags, flag, flag: Equatorial Guinea'],['🇬🇷','flag_gr','flag: Greece, flags, flag'],['🇬🇸','flag_gs','flag: South Georgia & South Sandwich Islands, flags, flag'],['🇬🇹','flag_gt','flags, flag: Guatemala, flag'],['🇬🇺','flag_gu','flag: Guam, flags, flag'],['🇬🇼','flag_gw','flag: Guinea-Bissau, flags, flag'],['🇬🇾','flag_gy','flag: Guyana, flags, flag'],['🇭🇰','flag_hk','flag: Hong Kong SAR China, flags, flag'],['🇭🇲','flag_hm','flags, flag, flag: Heard & McDonald Islands'],['🇭🇳','flag_hn','flags, flag, flag: Honduras'],['🇭🇷','flag_hr','flags, flag: Croatia, flag'],['🇭🇹','flag_ht','flags, flag: Haiti, flag'],['🇭🇺','flag_hu','flags, flag: Hungary, flag'],['🇮🇨','flag_ic','flags, flag, flag: Canary Islands'],['🇮🇩','flag_id','flags, flag: Indonesia, flag'],['🇮🇪','flag_ie','flags, flag: Ireland, flag'],['🇮🇱','flag_il','flags, flag: Israel, flag'],['🇮🇲','flag_im','flag: Isle of Man, flags, flag'],['🇮🇳','flag_in','flags, flag, flag: India'],['🇮🇴','flag_io','flags, flag: British Indian Ocean Territory, flag'],['🇮🇶','flag_iq','flag: Iraq, flags, flag'],['🇮🇷','flag_ir','flags, flag, flag: Iran'],['🇮🇸','flag_is','flags, flag: Iceland, flag'],['🇮🇹','flag_it','flags, flag: Italy, flag'],['🇯🇪','flag_je','flags, flag, flag: Jersey'],['🇯🇲','flag_jm','flags, flag, flag: Jamaica'],['🇯🇴','flag_jo','flag: Jordan, flags, flag'],['🇯🇵','flag_jp','flags, flag: Japan, flag'],['🇰🇪','flag_ke','flag: Kenya, flags, flag'],['🇰🇬','flag_kg','flag: Kyrgyzstan, flags, flag'],['🇰🇭','flag_kh','flag: Cambodia, flags, flag'],['🇰🇮','flag_ki','flag: Kiribati, flags, flag'],['🇰🇲','flag_km','flags, flag, flag: Comoros'],['🇰🇳','flag_kn','flags, flag: St. Kitts & Nevis, flag'],['🇰🇵','flag_kp','flag: North Korea, flags, flag'],['🇰🇷','flag_kr','flags, flag: South Korea, flag'],['🇰🇼','flag_kw','flags, flag, flag: Kuwait'],['🇰🇾','flag_ky','flags, flag: Cayman Islands, flag'],['🇰🇿','flag_kz','flags, flag: Kazakhstan, flag'],['🇱🇦','flag_la','flags, flag, flag: Laos'],['🇱🇧','flag_lb','flags, flag, flag: Lebanon'],['🇱🇨','flag_lc','flag: St. Lucia, flags, flag'],['🇱🇮','flag_li','flags, flag, flag: Liechtenstein'],['🇱🇰','flag_lk','flags, flag, flag: Sri Lanka'],['🇱🇷','flag_lr','flag: Liberia, flags, flag'],['🇱🇸','flag_ls','flag: Lesotho, flags, flag'],['🇱🇹','flag_lt','flags, flag: Lithuania, flag'],['🇱🇺','flag_lu','flags, flag, flag: Luxembourg'],['🇱🇻','flag_lv','flag: Latvia, flags, flag'],['🇱🇾','flag_ly','flags, flag: Libya, flag'],['🇲🇦','flag_ma','flags, flag, flag: Morocco'],['🇲🇨','flag_mc','flags, flag, flag: Monaco'],['🇲🇩','flag_md','flag: Moldova, flags, flag'],['🇲🇪','flag_me','flag: Montenegro, flags, flag'],['🇲🇫','flag_mf','flags, flag, flag: St. Martin'],['🇲🇬','flag_mg','flags, flag, flag: Madagascar'],['🇲🇭','flag_mh','flags, flag: Marshall Islands, flag'],['🇲🇰','flag_mk','flags, flag, flag: North Macedonia'],['🇲🇱','flag_ml','flag: Mali, flags, flag'],['🇲🇲','flag_mm','flags, flag: Myanmar (Burma), flag'],['🇲🇳','flag_mn','flag: Mongolia, flags, flag'],['🇲🇴','flag_mo','flags, flag: Macao SAR China, flag'],['🇲🇵','flag_mp','flags, flag: Northern Mariana Islands, flag'],['🇲🇶','flag_mq','flags, flag: Martinique, flag'],['🇲🇷','flag_mr','flag: Mauritania, flags, flag'],['🇲🇸','flag_ms','flags, flag, flag: Montserrat'],['🇲🇹','flag_mt','flags, flag: Malta, flag'],['🇲🇺','flag_mu','flags, flag, flag: Mauritius'],['🇲🇻','flag_mv','flag: Maldives, flags, flag'],['🇲🇼','flag_mw','flags, flag: Malawi, flag'],['🇲🇽','flag_mx','flag: Mexico, flags, flag'],['🇲🇾','flag_my','flags, flag: Malaysia, flag'],['🇲🇿','flag_mz','flags, flag: Mozambique, flag'],['🇳🇦','flag_na','flags, flag, flag: Namibia'],['🇳🇨','flag_nc','flags, flag, flag: New Caledonia'],['🇳🇪','flag_ne','flags, flag: Niger, flag'],['🇳🇫','flag_nf','flags, flag, flag: Norfolk Island'],['🇳🇬','flag_ng','flags, flag: Nigeria, flag'],['🇳🇮','flag_ni','flags, flag: Nicaragua, flag'],['🇳🇱','flag_nl','flags, flag, flag: Netherlands'],['🇳🇴','flag_no','flag: Norway, flags, flag'],['🇳🇵','flag_np','flags, flag, flag: Nepal'],['🇳🇷','flag_nr','flags, flag: Nauru, flag'],['🇳🇺','flag_nu','flag: Niue, flags, flag'],['🇳🇿','flag_nz','flag: New Zealand, flags, flag'],['🇴🇲','flag_om','flags, flag: Oman, flag'],['🇵🇦','flag_pa','flags, flag, flag: Panama'],['🇵🇪','flag_pe','flag: Peru, flags, flag'],['🇵🇫','flag_pf','flag: French Polynesia, flags, flag'],['🇵🇬','flag_pg','flags, flag: Papua New Guinea, flag'],['🇵🇭','flag_ph','flags, flag, flag: Philippines'],['🇵🇰','flag_pk','flag: Pakistan, flags, flag'],['🇵🇱','flag_pl','flags, flag: Poland, flag'],['🇵🇲','flag_pm','flags, flag, flag: St. Pierre & Miquelon'],['🇵🇳','flag_pn','flags, flag, flag: Pitcairn Islands'],['🇵🇷','flag_pr','flag: Puerto Rico, flags, flag'],['🇵🇸','flag_ps','flags, flag: Palestinian Territories, flag'],['🇵🇹','flag_pt','flag: Portugal, flags, flag'],['🇵🇼','flag_pw','flag: Palau, flags, flag'],['🇵🇾','flag_py','flag: Paraguay, flags, flag'],['🇶🇦','flag_qa','flag: Qatar, flags, flag'],['🇷🇪','flag_re','flags, flag, flag: Réunion'],['🇷🇴','flag_ro','flags, flag, flag: Romania'],['🇷🇸','flag_rs','flags, flag: Serbia, flag'],['🇷🇺','flag_ru','flags, flag, flag: Russia'],['🇷🇼','flag_rw','flags, flag, flag: Rwanda'],['🇸🇦','flag_sa','flags, flag, flag: Saudi Arabia'],['🇸🇧','flag_sb','flag: Solomon Islands, flags, flag'],['🇸🇨','flag_sc','flags, flag: Seychelles, flag'],['🇸🇩','flag_sd','flags, flag, flag: Sudan'],['🇸🇪','flag_se','flag: Sweden, flags, flag'],['🇸🇬','flag_sg','flags, flag, flag: Singapore'],['🇸🇭','flag_sh','flags, flag, flag: St. Helena'],['🇸🇮','flag_si','flags, flag: Slovenia, flag'],['🇸🇯','flag_sj','flag: Svalbard & Jan Mayen, flags, flag'],['🇸🇰','flag_sk','flags, flag, flag: Slovakia'],['🇸🇱','flag_sl','flag: Sierra Leone, flags, flag'],['🇸🇲','flag_sm','flags, flag: San Marino, flag'],['🇸🇳','flag_sn','flags, flag: Senegal, flag'],['🇸🇴','flag_so','flags, flag, flag: Somalia'],['🇸🇷','flag_sr','flag: Suriname, flags, flag'],['🇸🇸','flag_ss','flags, flag: South Sudan, flag'],['🇸🇹','flag_st','flags, flag: São Tomé & Príncipe, flag'],['🇸🇻','flag_sv','flags, flag: El Salvador, flag'],['🇸🇽','flag_sx','flags, flag, flag: Sint Maarten'],['🇸🇾','flag_sy','flags, flag: Syria, flag'],['🇸🇿','flag_sz','flags, flag: Eswatini, flag'],['🇹🇦','flag_ta','flags, flag: Tristan da Cunha, flag'],['🇹🇨','flag_tc','flags, flag, flag: Turks & Caicos Islands'],['🇹🇩','flag_td','flags, flag: Chad, flag'],['🇹🇫','flag_tf','flag: French Southern Territories, flags, flag'],['🇹🇬','flag_tg','flags, flag, flag: Togo'],['🇹🇭','flag_th','flag: Thailand, flags, flag'],['🇹🇯','flag_tj','flag: Tajikistan, flags, flag'],['🇹🇰','flag_tk','flags, flag: Tokelau, flag'],['🇹🇱','flag_tl','flags, flag: Timor-Leste, flag'],['🇹🇲','flag_tm','flags, flag, flag: Turkmenistan'],['🇹🇳','flag_tn','flag: Tunisia, flags, flag'],['🇹🇴','flag_to','flags, flag, flag: Tonga'],['🇹🇷','flag_tr','flags, flag: Turkey, flag'],['🇹🇹','flag_tt','flags, flag, flag: Trinidad & Tobago'],['🇹🇻','flag_tv','flag: Tuvalu, flags, flag'],['🇹🇼','flag_tw','flag: Taiwan, flags, flag'],['🇹🇿','flag_tz','flag: Tanzania, flags, flag'],['🇺🇦','flag_ua','flags, flag, flag: Ukraine'],['🇺🇬','flag_ug','flags, flag: Uganda, flag'],['🇺🇲','flag_um','flags, flag, flag: U.S. Outlying Islands'],['🇺🇸','flag_us','flags, flag, flag: United States'],['🇺🇾','flag_uy','flags, flag, flag: Uruguay'],['🇺🇿','flag_uz','flags, flag, flag: Uzbekistan'],['🇻🇦','flag_va','flags, flag: Vatican City, flag'],['🇻🇨','flag_vc','flag: St. Vincent & Grenadines, flags, flag'],['🇻🇪','flag_ve','flags, flag, flag: Venezuela'],['🇻🇬','flag_vg','flag: British Virgin Islands, flags, flag'],['🇻🇮','flag_vi','flag: U.S. Virgin Islands, flags, flag'],['🇻🇳','flag_vn','flags, flag: Vietnam, flag'],['🇻🇺','flag_vu','flags, flag: Vanuatu, flag'],['🇼🇫','flag_wf','flag: Wallis & Futuna, flags, flag'],['🇼🇸','flag_ws','flag: Samoa, flags, flag'],['🇽🇰','flag_xk','flags, flag, flag: Kosovo'],['🇾🇪','flag_ye','flags, flag, flag: Yemen'],['🇾🇹','flag_yt','flags, flag, flag: Mayotte'],['🇿🇦','flag_za','flags, flag: South Africa, flag'],['🇿🇲','flag_zm','flags, flag: Zambia, flag'],['🇿🇼','flag_zw','flags, flag: Zimbabwe, flag'],['🏳️‍🌈','rainbow_flag','flag, rainbow flag, pride, gay, flags'],['🏳️‍⚧️','transgender_flag','trans, pride, flag, flags']];} \ No newline at end of file +function zenGlobalEmojis() { return [['⌚','watch','watch, clock, time, wristwatch'],['⌛','hourglass','hourglass done, time, sand, clock'],['⏪','rewind','arrow, blue, rewind, fast reverse button, left, back'],['⏫','arrow_double_up','increase, arrow, fast up button, blue, up'],['⏬','arrow_double_down','decrease, down, arrow, blue, fast down button'],['⏰','alarm_clock','alarm clock, clock, alarm, time, red'],['⏳','hourglass_flowing_sand','hourglass not done, time, sand, clock'],['⚽','soccer','sports, football, soccer ball, ball, soccer, soccer ball,'],['⚾','baseball','ball, baseball, sports'],['⛄','snowman','snowman, snowman without snow, christmas, holidays, snow'],['⛅','partly_sunny','sun, sun behind cloud, cloudy, sunny, weather'],['⛎','ophiuchus','zodiac, horoscope, Ophiuchus, purple'],['⛔','no_entry','sign, red, stop, no entry'],['⛪','church','church, building, religion, worship, faith, holy'],['⛲','fountain','fountain, water, garden'],['⛳','golf','sports, golf, flag in hole, flag'],['⛵','sailboat','vessel, vacation, sailing, sea, ship, sailboat, water, boat, travel, ocean'],['⛺','tent','camp, camping, outdoor, tent, camping, shelter, nature, vacation'],['⛽','fuelpump','oil, petrol, fuel pump, gas, red, gas station, fuel'],['✅','white_check_mark','approve, check, check mark, tick, check mark button, accept, yes, success, task'],['✊','fist','justice, raised fist, solidarity, empowerment, fist, strength'],['✋','raised_hand','hand, stop, halt, raised hand'],['✨','sparkles','sparkles, stars, shine, AI, magic, beauty, creativity'],['❌','x','cross mark, cross, wrong, no, red'],['❎','negative_squared_cross_mark','cross, no, green,, cross mark button'],['❓','question','curiosity, question mark, question, punctuation, red'],['⭐','star','star, five, achievement, favorite, yellow, gold, space, universe'],['⭕','o','hoop, hollow red circle, o, circle, red, round'],['🀄','mahjong','mahjong red dragon, china, game'],['🃏','black_joker','card, joker, game, deck, gamble'],['🆎','ab','red,, AB button (blood type)'],['🆑','cl','CL button, red'],['🆒','cool','cool, blue, COOL button'],['🆓','free','free, blue, FREE button'],['🆔','id','authentication, security, purple, identification, id, verification, ID button'],['🆕','new','new, blue, NEW button'],['🆖','ng','blue, ana ng, NG button, ng'],['🆗','ok','blue, okay, ok, OK button'],['🆘','sos','SOS button, emergency, danger, red, help, sos'],['🆙','up','UP! button, up, blue'],['🆚','vs','versus, duel, orange, contest, challenge, vs, battle, competition, VS button'],['🈁','koko','here, blue, japanese, Japanese here button'],['🈚','u7121','Japanese free of charge button, orange, japanese'],['🈯','u6307','Japanese reserved button, japanese, green'],['🈲','u7981','Japanese prohibited button, red, japanese'],['🈳','u7a7a','blue, Japanese vacancy button, japanese'],['🈴','u5408','Japanese passing grade button, red, japanese'],['🈵','u6e80','Japanese no vacancy button, red, japanese'],['🈶','u6709','Japanese not free of charge button, orange, japanese'],['🈸','u7533','Japanese application button, orange, japanese'],['🈹','u5272','Japanese discount button, red, japanese'],['🈺','u55b6','Japanese open for business button, orange, japanese'],['🉐','ideograph_advantage','Japanese bargain button, red, japanese'],['🉑','accept','Japanese acceptable button, orange, japanese'],['🌀','cyclone','cyclone, spiral, Zen, purple, swirl, storm'],['🌁','foggy','foggy, bridge, cloudy'],['🌂','closed_umbrella',', umbrella, purple, rain, closed umbrella, weather'],['🌃','night_with_stars','night, city, night with stars, scenery'],['🌄','sunrise_over_mountains','sunrise, sunrise over mountains, sun, sunset, nature, scenery'],['🌅','sunrise','sun, sunset, sunrise, scenery, nature'],['🌆','city_dusk','cityscape at dusk, city,, scenery'],['🌇','city_sunset','city, evening, sunset, scenery'],['🌈','rainbow','rainbow, pride, gay'],['🌉','bridge_at_night','night, bridge, bridge at night'],['🌊','ocean','water wave, tsunami, water, blue, ocean, art, sea, wave'],['🌋','volcano','volcano, eruption, lava, fire, geological'],['🌌','milky_way','science, milky way, galaxy, cosmos, stars, blue, nebula'],['🌍','earth_africa','africa, blue, planet, school, map, world, earth, globe, globe showing Europe-Africa, geography'],['🌎','earth_americas','blue, planet, america, school, map, globe showing Americas, world, earth, globe, geography'],['🌏','earth_asia','globe showing Asia-Australia, blue, asia, planet, school, map, world, earth, globe, australia, geography'],['🌐','globe_with_meridians','globe with meridians, blue, tech, internet, www, world, network, technology, web'],['🌑','new_moon','moon, lunar, purple, night, new moon, space, astronomy'],['🌒','waxing_crescent_moon','night, waxing crescent moon, astronomy, space, moon'],['🌓','first_quarter_moon','night, first quarter moon, astronomy, space, moon'],['🌔','waxing_gibbous_moon','night, waxing gibbous moon, astronomy, space, moon'],['🌕','full_moon','night, astronomy, full moon, space, yellow, moon'],['🌖','waning_gibbous_moon','night, astronomy, waning gibbous moon, space, moon'],['🌗','last_quarter_moon','night, astronomy, last quarter moon, space, moon'],['🌘','waning_crescent_moon','night, astronomy, waning crescent moon, space, moon'],['🌙','crescent_moon','night, astronomy, crescent moon, space, moon'],['🌚','new_moon_with_face','night, face, new moon face, astronomy, purple, space, moon'],['🌛','first_quarter_moon_with_face','night, face, astronomy, first quarter moon face, smile, space, yellow, moon'],['🌜','last_quarter_moon_with_face','night, face, astronomy, smile, last quarter moon face, space, yellow, moon'],['🌝','full_moon_with_face','night, face, full moon face, astronomy, smile, space, yellow, moon'],['🌞','sun_with_face','sun with face, night, face, astronomy, smile, space, yellow, moon'],['🌟','star2','sparkle, night, star, glowing star, yellow'],['🌠','stars','night, falling, star, cosmos, shooting star'],['🌭','hotdog','hotdog, hot dog, food'],['🌮','taco','taco, food'],['🌯','burrito','food, wrap, shawarma, burrito'],['🌰','chestnut','food, chestnut, onion'],['🌱','seedling',', green, plant, growth, seedling'],['🌲','evergreen_tree','holidays, christmas, green, evergreen tree, spruce, tree'],['🌳','deciduous_tree','oak, deciduous tree, environment, plant, nature, forest, tree, green'],['🌴','palm_tree','palm tree, vacation, palm, island, tree, beach'],['🌵','cactus','cactus, desert, green, nature, plant'],['🌷','tulip','flower, tulip, pink, nature, plant'],['🌸','cherry_blossom','pink, bloom, plant, nature, flower, sakura, cherry blossom'],['🌹','rose','flower, rose, red, nature, plant'],['🌺','hibiscus','hibiscus, pink, plant, nature, flower'],['🌻','sunflower','sunflower, nature, plant, flower, yellow'],['🌼','blossom','blossom, plant, nature, flower, white'],['🌽','corn','food, corn, ear of corn'],['🌾','ear_of_rice','food, sheaf of rice, wheat'],['🌿','herb','herb, plant'],['🍀','four_leaf_clover','lucky, four leaf clover, fortune, clover, green, plant'],['🍁','maple_leaf','maple leaf, autumn, plant, nature, leaf, fall, red, canada'],['🍂','fallen_leaf','brown, leaf, autumn, plant, nature, fall, dead leaves, fallen leaf'],['🍃','leaves','nature, green, leaf, leaf fluttering in wind, plant'],['🍄','mushroom','mushroom, nature, plant, fungi, toadstool'],['🍅','tomato','tomato, food, vegetable, red'],['🍆','eggplant','eggplant, food, vegetable, purple'],['🍇','grapes','food, fruit, grapes, grape, purple'],['🍈','melon','melon, fruit, food'],['🍉','watermelon','watermelon, fruit, food, red'],['🍊','tangerine','food, fruit, tangerine, orange'],['🍋','lemon','lemon, food, fruit, yellow'],['🍌','banana','banana, food, fruit, berry, yellow'],['🍍','pineapple','pineapple, food, fruit'],['🍎','apple','food, red apple, fruit, apple, school,, red'],['🍏','green_apple','food, fruit, green, apple, green apple'],['🍐','pear','pear, food, fruit, green'],['🍑','peach','peach, food, fruit'],['🍒','cherries','food, fruit, cherries, cherry, red'],['🍓','strawberry','strawberry, berry, fruit, food, red'],['🍔','hamburger','hamburger, america, food'],['🍕','pizza','pizza, food'],['🍖','meat_on_bone','food, meat on bone, ham'],['🍗','poultry_leg','chicken, poultry leg, food'],['🍘','rice_cracker','rice cracker, rice'],['🍙','rice_ball','onigiri, rice, rice ball, food'],['🍚','rice','food, rice, cooked rice'],['🍛','curry','food, rice, curry, curry rice'],['🍜','ramen','food, steaming bowl, ramen, noodles'],['🍝','spaghetti','food, pasta, spaghetti'],['🍞','bread','bread, food'],['🍟','fries','fries, french fries, french, food'],['🍠','sweet_potato','food, roasted, roasted sweet potato, sweet, potato'],['🍡','dango','dango, food'],['🍢','oden','oden, food'],['🍣','sushi','sushi, salmon, food'],['🍤','fried_shrimp','food, prawn, fried shrimp'],['🍥','fish_cake',', fish cake with swirl'],['🍦','icecream','desert, icecrean, soft ice cream, food'],['🍧','shaved_ice','desert, icecrean, shaved ice, food'],['🍨','ice_cream','desert, ice cream, icecrean, food'],['🍩','doughnut','desert, donut, doughnut, food'],['🍪','cookie','cookie, desert, food'],['🍫','chocolate_bar','desert, chocolate, chocolate bar, food'],['🍬','candy','candy, desert, food'],['🍭','lollipop','desert, candy, lollipop, food'],['🍮','custard','custard, food, dessert'],['🍯','honey_pot','food, honey, honey pot'],['🍰','cake','food, shortcake, cakedesert'],['🍱','bento','bento, rice, bento box, food'],['🍲','stew','food, soup, pot of food'],['🍳','cooking','food, cooking, omelette, egg'],['🍴','fork_and_knife','cutlery, food, fork and knife, fork, knife'],['🍵','tea','chai, food, drink, tea, teacup without handle'],['🍶','sake','sake, drink'],['🍷','wine_glass','food, wine glass, wine, drink'],['🍸','cocktail','food, glass, cocktail glass, drink, cocktail, martini'],['🍹','tropical_drink','drink, tropical drink, long island, food'],['🍺','beer','food, beer mug, drink, beer'],['🍻','beers','food, clinking beer mugs, drink, beer'],['🍼','baby_bottle','food, baby bottle, drink, baby, milk'],['🍾','champagne','drink, bottle with popping cork, champagne, food'],['🍿','popcorn','popcorn, food'],['🎀','ribbon','decoration, present, bow, ribbon, cute'],['🎁','gift','wrapped gift, present, christmas'],['🎂','birthday','birthday, birthday cake, cake'],['🎃','jack_o_lantern','scary, pumpkin, spooky, fall, orange, halloween, jack-o-lantern'],['🎄','christmas_tree','Christmas tree, tree, christmas, holidays'],['🎅','santa','santa, Santa Claus, christmas, holidays'],['🎆','fireworks','fireworks, party'],['🎇','sparkler','fireworks, sparkler, party'],['🎈','balloon','baloon, red, balloon'],['🎉','tada','confetti, party, party popper, celebration'],['🎊','confetti_ball','confetti, party, confetti ball, celebration'],['🎋','tanabata_tree','tanabata, tree, tanabata tree'],['🎌','crossed_flags',', crossed flags'],['🎍','bamboo','bamboo, pine decoration'],['🎎','dolls',', Japanese dolls'],['🎏','flags',', carp streamer'],['🎐','wind_chime',', wind chime'],['🎑','rice_scene',', moon viewing ceremony'],['🎒','school_satchel','school, backpack, bag'],['🎓','mortar_board','graduation, graduate, education, school, graduation cap, university'],['🎠','carousel_horse','park, carousel, carousel horse, pony'],['🎡','ferris_wheel','park, ferris, ferris wheel, wheel'],['🎢','roller_coaster','park, roller coaster, rollercoaster'],['🎣','fishing_pole_and_fish','fishing, fishing pole, fish, rod'],['🎤','microphone','microphone, speech, talk, singing'],['🎥','movie_camera','recording, movie camera, cinema, film, video, camera, content creation'],['🎦','cinema','camera, blue, recording, video, film, cinema'],['🎧','headphones','music, headphone, headphones, audio'],['🎨','art','colors, artist palette, creativity, design, painting, art, inspiration'],['🎩','tophat','hat, top hat, magic'],['🎪','circus_tent','circus, circus tent'],['🎫','ticket','ticket'],['🎬','clapper','video editing, media, video, clapper board, audiovisual'],['🎭','performing_arts','theater, performing arts, drama, masks'],['🎮','video_game','xbox, ps4, gaming, video game, playstation'],['🎯','dart','direct hit, goal, target, task'],['🎰','slot_machine','slot, casino, slot machine, games, gambling'],['🎱','8ball','billiard, games, ball, 8, eight, pool 8 ball'],['🎲','game_die','dice, luck, games, one, 1, game die'],['🎳','bowling','bowling, games, games'],['🎴','flower_playing_cards','play, card, flower playing cards'],['🎵','musical_note','note, musical note, song, music'],['🎶','notes','note, song, music, musical notes'],['🎷','saxophone','instrument, song, music, sax, saxophone'],['🎸','guitar','music, guitar, instrument, electric, song'],['🎹','musical_keyboard','instrument, song, music, piano, musical keyboard'],['🎺','trumpet','music, trumpet, instrument, song'],['🎻','violin','music, instrument, violin, sound'],['🎼','musical_score','musical score, sound, music'],['🎽','running_shirt_with_sash','clothes, running shirt, vest'],['🎾','tennis','tennis, sport'],['🎿','ski','scating, sport, skis'],['🏀','basketball','basketball, sport, orange'],['🏁','checkered_flag','finish, sport, chequered flag, race'],['🏂','snowboarder','snowboarder, snowboard, sport, snow'],['🏃','person_running','person running, sport, running'],['🏄','person_surfing','person surfing, surfing, sport'],['🏅','medal','gold, win, medal, sports medal'],['🏆','trophy','trophy, win, gold'],['🏇','horse_racing','horse racing, horse, sport, racing'],['🏈','football','american football, brown, football, sport'],['🏉','rugby_football','rugby football, football, sport'],['🏊','person_swimming','sport, swimming, person swimming'],['🏏','cricket_game','baseball, sport, cricket, cricket game'],['🏐','volleyball','white, football, volleyball, sport'],['🏑','field_hockey','hockey, field hockey, sport, field'],['🏒','hockey','hockey, ice hockey, sport'],['🏓','ping_pong','ping pong, tennis, sport'],['🥋', 'martial_arts_uniform', 'martial arts uniform, martial arts, judo, bjj, jiu jitsu, kimono, gi, fighting, sport'],['🏠','house','home, house, building'],['🏡','house_with_garden','building, house with garden, home, house'],['🏢','office','office building, work, building, office'],['🏣','post_office','building, post, office, Japanese post office'],['🏤','european_post_office','post office, building, post, office'],['🏥','hospital','hospital, building, health'],['🏦','bank','bank, money, building'],['🏧','atm','atm, ATM sign, blue'],['🏨','hotel','hotel, building'],['🏩','love_hotel','love, building, hotel, love hotel'],['🏪','convenience_store','store, building, shop, groceries, convenience store, convenience'],['🏫','school','school, building'],['🏬','department_store','store, building, department store'],['🏭','factory','factory, work, building'],['🏮','izakaya_lantern','lamp, red paper lantern, light'],['🏯','japanese_castle','building, Japanese castle, temple, castle, fortress'],['🏰','european_castle','temple, castle, fortress, building'],['🏴','flag_black','black flag, flag, black'],['🏸','badminton','badminton, racket, sport'],['🏹','bow_and_arrow','archery, bow and arrow, sport'],['🏺','amphora','amphora, vase'],['🐀','rat','animal, rat'],['🐁','mouse2','animal, mouse'],['🐂','ox','animal, ox'],['🐃','water_buffalo',', water buffalo'],['🐄','cow2','animal, cow'],['🐅','tiger2','animal, tiger'],['🐆','leopard','animal, leopard'],['🐇','rabbit2','animal, rabbit, bunny, hair'],['🐈','cat2','animal, cat'],['🐉','dragon','animal, dragon'],['🐊','crocodile','alagator, animal, crocodile, green'],['🐋','whale2','animal, whale, blue'],['🐌','snail','animal, snail'],['🐍','snake','animal, snake'],['🐎','racehorse','animal, horse'],['🐏','ram','animal, ram'],['🐐','goat','animal, goat'],['🐑','sheep','animal, ewe'],['🐒','monkey','animal, monkey'],['🐓','rooster','animal, rooster'],['🐔','chicken','chicken, animal'],['🐕','dog2','animal, dog'],['🐖','pig2','animal, pig'],['🐗','boar','animal, boar'],['🐘','elephant','animal, elephant'],['🐙','octopus','animal, octopus'],['🐚','shell','spiral shell, seashell, sea, beach, ocean'],['🐛','bug','animal, insect, bug'],['🐜','ant','animal, insect, ant, bug'],['🐝','bee','animal, insect, bug, honeybee'],['🐞','beetle','animal, insect, bug, lady beetle'],['🐟','fish','animal, fish'],['🐠','tropical_fish','tropical fish, animal'],['🐡','blowfish','animal, blowfish'],['🐢','turtle','animal, turtle, green'],['🐣','hatching_chick','hatching chick, animal'],['🐤','baby_chick','animal, baby chick'],['🐥','hatched_chick','animal, front-facing baby chick'],['🐦','bird','animal, bird'],['🐧','penguin','linux, animal, penguin'],['🐨','koala','animal, koala'],['🐩','poodle','animal, poodle'],['🐪','dromedary_camel','animal, camel'],['🐫','camel','animal, two-hump camel'],['🐬','dolphin','animal, dolphin'],['🐭','mouse','animal, mouse face, face'],['🐮','cow','animal, face, cow face'],['🐯','tiger','tiger face, animal, face'],['🐰','rabbit','animal, cute, rabbit face'],['🐱','cat','animal, cat face, face, cute'],['🐲','dragon_face','animal, dragon face'],['🐳','whale','animal, spouting whale'],['🐴','horse','animal, face, horse face'],['🐵','monkey_face','monkey face, animal, face'],['🐶','dog','animal, face, dog face'],['🐷','pig','animal, face, pig face'],['🐸','frog','frog, animal, face'],['🐹','hamster','animal, face, hamster'],['🐺','wolf','animal, face, wolf'],['🐻','bear','animal, face, bear'],['🐼','panda_face','animal, panda'],['🐽','pig_nose','animal, pig nose, nose'],['🐾','feet','animal, tracks, paw prints'],['👀','eyes','looking, eyes'],['👂','ear','listen, sound, ear'],['👃','nose','nose, smell'],['👄','lips','mouth'],['👅','tongue','tongue, silly, mouth'],['👆','point_up_2',', backhand index pointing up'],['👇','point_down',', backhand index pointing down'],['👈','point_left',', backhand index pointing left'],['👉','point_right',', backhand index pointing right'],['👊','punch',', oncoming fist'],['👋','wave',', waving hand'],['👌','ok_hand',', OK hand'],['👍','thumbsup',', thumbs up'],['👎','thumbsdown',', thumbs down'],['👏','clap',', clapping hands'],['👐','open_hands',', open hands'],['👑','crown',', crown'],['👒','womans_hat',', woman’s hat'],['👓','eyeglasses',', glasses'],['👔','necktie',', necktie'],['👕','shirt',', t-shirt'],['👖','jeans',', jeans'],['👗','dress',', dress'],['👘','kimono',', kimono'],['👙','bikini',', bikini'],['👚','womans_clothes',', woman’s clothes'],['👛','purse',', purse'],['👜','handbag',', handbag'],['👝','pouch',', clutch bag'],['👞','mans_shoe',', man’s shoe'],['👟','athletic_shoe',', running shoe'],['👠','high_heel',', high-heeled shoe'],['👡','sandal',', woman’s sandal'],['👢','boot',', woman’s boot'],['👣','footprints',', footprints'],['👤','bust_in_silhouette',', bust in silhouette'],['👥','busts_in_silhouette',', busts in silhouette'],['👦','boy',', boy'],['👧','girl',', girl'],['👨','man',', man'],['👩','woman',', woman'],['👪','family',', family'],['👫','couple',', woman and man holding hands'],['👬','two_men_holding_hands',', men holding hands'],['👭','two_women_holding_hands',', women holding hands'],['👮','police_officer',', police officer'],['👯','people_with_bunny_ears_partying',', people with bunny ears'],['👰','bride_with_veil',', bride with veil'],['👱','blond_haired_person',', person: blond hair'],['👲','man_with_chinese_cap',', man with skullcap'],['👳','person_wearing_turban',', person wearing turban'],['👴','older_man',', old man'],['👵','older_woman',', old woman'],['👶','baby',', baby'],['👷','construction_worker',', construction worker'],['👸','princess',', princess'],['👹','japanese_ogre',', ogre'],['👺','japanese_goblin',', goblin'],['👻','ghost','ghost, halloween'],['👼','angel',', baby angel'],['👽','alien',', alien'],['👾','space_invader',', alien monster'],['👿','imp',', angry face with horns'],['💀','skull','spooky, skull, horror, bones'],['💁','person_tipping_hand','person tipping hand, questions'],['💂','guard',', guard'],['💃','dancer',', woman dancing'],['💄','lipstick','makeup, lipstick'],['💅','nail_care','beauty, nail polish, makeup'],['💆','person_getting_massage',', person getting massage'],['💇','person_getting_haircut',', person getting haircut'],['💈','barber',', barber pole'],['💉','syringe',', syringe'],['💊','pill',', pill'],['💋','kiss',', kiss mark'],['💌','love_letter',', love letter'],['💍','ring',', ring'],['💎','gem',', gem stone'],['💏','couplekiss',', kiss'],['💐','bouquet',', bouquet'],['💑','couple_with_heart',', couple with heart'],['💒','wedding',', wedding'],['💓','heartbeat',', beating heart'],['💔','broken_heart',', broken heart'],['💕','two_hearts',', two hearts'],['💖','sparkling_heart',', sparkling heart'],['💗','heartpulse',', growing heart'],['💘','cupid',', heart with arrow'],['💙','blue_heart',', blue heart'],['💚','green_heart',', green heart'],['💛','yellow_heart',', yellow heart'],['💜','purple_heart',', purple heart'],['💝','gift_heart',', heart with ribbon'],['💞','revolving_hearts',', revolving hearts'],['💟','heart_decoration',', heart decoration'],['💠','diamond_shape_with_a_dot_inside',', diamond with a dot'],['💡','bulb',', light bulb'],['💢','anger',', anger symbol'],['💣','bomb',', bomb'],['💤','zzz',', zzz'],['💥','boom',', collision'],['💦','sweat_drops',', sweat droplets'],['💧','droplet',', droplet'],['💨','dash',', dashing away'],['💩','poop',', pile of poo'],['💪','muscle',', flexed biceps'],['💫','dizzy',', dizzy'],['💬','speech_balloon',', speech balloon'],['💭','thought_balloon',', thought balloon'],['💮','white_flower',', white flower'],['💯','100',', hundred points'],['💰','moneybag',', money bag'],['💱','currency_exchange',', currency exchange'],['💲','heavy_dollar_sign',', heavy dollar sign'],['💳','credit_card',', credit card'],['💴','yen',', yen banknote'],['💵','dollar',', dollar banknote'],['💶','euro',', euro banknote'],['💷','pound',', pound banknote'],['💸','money_with_wings',', money with wings'],['💹','chart',', chart increasing with yen'],['💺','seat',', seat'],['💻','computer',', laptop'],['💼','briefcase',', briefcase'],['💽','minidisc',', computer disk'],['💾','floppy_disk',', floppy disk'],['💿','cd',', optical disk'],['📀','dvd',', dvd'],['📁','file_folder',', file folder'],['📂','open_file_folder',', open file folder'],['📃','page_with_curl',', page with curl'],['📄','page_facing_up',', page facing up'],['📅','date',', calendar'],['📆','calendar',', tear-off calendar'],['📇','card_index',', card index'],['📈','chart_with_upwards_trend',', chart increasing'],['📉','chart_with_downwards_trend',', chart decreasing'],['📊','bar_chart',', bar chart'],['📋','clipboard',', clipboard'],['📌','pushpin',', pushpin'],['📍','round_pushpin',', round pushpin'],['📎','paperclip',', paperclip'],['📏','straight_ruler',', straight ruler'],['📐','triangular_ruler',', triangular ruler'],['📑','bookmark_tabs',', bookmark tabs'],['📒','ledger',', ledger'],['📓','notebook',', notebook'],['📔','notebook_with_decorative_cover',', notebook with decorative cover'],['📕','closed_book',', closed book'],['📖','book',', open book'],['📗','green_book',', green book'],['📘','blue_book',', blue book'],['📙','orange_book',', orange book'],['📚','books','books, study, school'],['📛','name_badge',', name badge'],['📜','scroll',', scroll'],['📝','pencil','pencil, memo, note, school, study'],['📞','telephone_receiver','call, telephone receiver, phone'],['📟','pager',', pager'],['📠','fax',', fax machine'],['📡','satellite',', satellite antenna'],['📢','loudspeaker',', loudspeaker'],['📣','mega',', megaphone'],['📤','outbox_tray',', outbox tray'],['📥','inbox_tray',', inbox tray'],['📦','package',', package'],['📧','e-mail','mail, e-mail'],['📨','incoming_envelope','mail, incoming envelope'],['📩','envelope_with_arrow','mail, envelope with arrow'],['📪','mailbox_closed','closed mailbox with lowered flag, mail'],['📫','mailbox','mail, closed mailbox with raised flag'],['📬','mailbox_with_mail','mail, open mailbox with raised flag'],['📭','mailbox_with_no_mail','mail, open mailbox with lowered flag'],['📮','postbox',', postbox'],['📯','postal_horn',', postal horn'],['📰','newspaper',', newspaper'],['📱','iphone',', mobile phone'],['📲','calling',', mobile phone with arrow'],['📳','vibration_mode',', vibration mode'],['📴','mobile_phone_off',', mobile phone off'],['📵','no_mobile_phones',', no mobile phones'],['📶','signal_strength',', antenna bars'],['📷','camera','photo, photography, camera'],['📸','camera_with_flash','camera with flash, photo, photography'],['📹','video_camera',', video camera'],['📺','tv',', television'],['📻','radio',', radio'],['📼','vhs',', videocassette'],['📿','prayer_beads',', prayer beads'],['🔀','twisted_rightwards_arrows',', shuffle tracks button'],['🔁','repeat',', repeat button'],['🔂','repeat_one',', repeat single button'],['🔃','arrows_clockwise',', clockwise vertical arrows'],['🔄','arrows_counterclockwise',', counterclockwise arrows button'],['🔅','low_brightness',', dim button'],['🔆','high_brightness',', bright button'],['🔇','mute',', muted speaker'],['🔈','speaker',', speaker low volume'],['🔉','sound',', speaker medium volume'],['🔊','loud_sound',', speaker high volume'],['🔋','battery',', battery'],['🔌','electric_plug',', electric plug'],['🔍','mag','magnifying glass tilted left, search'],['🔎','mag_right','search, magnifying glass tilted right'],['🔏','lock_with_ink_pen',', locked with pen'],['🔐','closed_lock_with_key',', locked with key'],['🔑','key',', key'],['🔒','lock',', locked'],['🔓','unlock',', unlocked'],['🔔','bell',', bell'],['🔕','no_bell',', bell with slash'],['🔖','bookmark',', bookmark'],['🔗','link',', link'],['🔘','radio_button',', radio button'],['🔙','back',', BACK arrow'],['🔚','end',', END arrow'],['🔛','on',', ON! arrow'],['🔜','soon',', SOON arrow'],['🔝','top',', TOP arrow'],['🔞','underage',', no one under eighteen'],['🔟','keycap_ten',', keycap: 10'],['🔠','capital_abcd',', input latin uppercase'],['🔡','abcd',', input latin lowercase'],['🔢','1234',', input numbers'],['🔣','symbols',', input symbols'],['🔤','abc',', input latin letters'],['🔥','fire',', fire'],['🔦','flashlight',', flashlight'],['🔧','wrench',', wrench'],['🔨','hammer',', hammer'],['🔩','nut_and_bolt',', nut and bolt'],['🔪','knife',', kitchen knife'],['🔫','gun',', pistol'],['🔬','microscope',', microscope'],['🔭','telescope',', telescope'],['🔮','crystal_ball',', crystal ball'],['🔯','six_pointed_star',', dotted six-pointed star'],['🔰','beginner',', Japanese symbol for beginner'],['🔱','trident',', trident emblem'],['🔲','black_square_button',', black square button'],['🔳','white_square_button',', white square button'],['🔴','red_circle',', red circle'],['🔵','blue_circle',', blue circle'],['🔶','large_orange_diamond',', large orange diamond'],['🔷','large_blue_diamond',', large blue diamond'],['🔸','small_orange_diamond',', small orange diamond'],['🔹','small_blue_diamond',', small blue diamond'],['🔺','small_red_triangle',', red triangle pointed up'],['🔻','small_red_triangle_down',', red triangle pointed down'],['🔼','arrow_up_small',', upwards button'],['🔽','arrow_down_small',', downwards button'],['🕋','kaaba',', kaaba'],['🕌','mosque',', mosque'],['🕍','synagogue',', synagogue'],['🕎','menorah',', menorah'],['🕐','clock1',', one o’clock'],['🕑','clock2',', two o’clock'],['🕒','clock3',', three o’clock'],['🕓','clock4',', four o’clock'],['🕔','clock5',', five o’clock'],['🕕','clock6',', six o’clock'],['🕖','clock7',', seven o’clock'],['🕗','clock8',', eight o’clock'],['🕘','clock9',', nine o’clock'],['🕙','clock10',', ten o’clock'],['🕚','clock11',', eleven o’clock'],['🕛','clock12',', twelve o’clock'],['🕜','clock130',', one-thirty'],['🕝','clock230',', two-thirty'],['🕞','clock330',', three-thirty'],['🕟','clock430',', four-thirty'],['🕠','clock530',', five-thirty'],['🕡','clock630',', six-thirty'],['🕢','clock730',', seven-thirty'],['🕣','clock830',', eight-thirty'],['🕤','clock930',', nine-thirty'],['🕥','clock1030',', ten-thirty'],['🕦','clock1130',', eleven-thirty'],['🕧','clock1230',', twelve-thirty'],['🖕','middle_finger',', middle finger'],['🖖','vulcan',', vulcan salute'],['🗻','mount_fuji',', mount fuji'],['🗼','tokyo_tower',', Tokyo tower'],['🗽','statue_of_liberty',', Statue of Liberty'],['🗾','japan',', map of Japan'],['🗿','moyai',', moai'],['😀','grinning',', grinning face'],['😁','grin',', beaming face with smiling eyes'],['😂','joy',', face with tears of joy'],['😃','smiley',', grinning face with big eyes'],['😄','smile',', grinning face with smiling eyes'],['😅','sweat_smile',', grinning face with sweat'],['😆','laughing',', grinning squinting face'],['😇','innocent',', smiling face with halo'],['😈','smiling_imp',', smiling face with horns'],['😉','wink',', winking face'],['😊','blush',', smiling face with smiling eyes'],['😋','yum',', face savoring food'],['😌','relieved',', relieved face'],['😍','heart_eyes',', smiling face with heart-eyes'],['😎','sunglasses',', smiling face with sunglasses'],['😏','smirk',', smirking face'],['😐','neutral_face',', neutral face'],['😑','expressionless',', expressionless face'],['😒','unamused',', unamused face'],['😓','sweat',', downcast face with sweat'],['😔','pensive',', pensive face'],['😕','confused',', confused face'],['😖','confounded',', confounded face'],['😗','kissing',', kissing face'],['😘','kissing_heart',', face blowing a kiss'],['😙','kissing_smiling_eyes',', kissing face with smiling eyes'],['😚','kissing_closed_eyes',', kissing face with closed eyes'],['😛','stuck_out_tongue',', face with tongue'],['😜','stuck_out_tongue_winking_eye',', winking face with tongue'],['😝','stuck_out_tongue_closed_eyes',', squinting face with tongue'],['😞','disappointed',', disappointed face'],['😟','worried',', worried face'],['😠','angry',', angry face'],['😡','rage',', pouting face'],['😢','cry',', crying face'],['😣','persevere',', persevering face'],['😤','triumph',', face with steam from nose'],['😥','disappointed_relieved',', sad but relieved face'],['😦','frowning',', frowning face with open mouth'],['😧','anguished',', anguished face'],['😨','fearful',', fearful face'],['😩','weary',', weary face'],['😪','sleepy',', sleepy face'],['😫','tired_face',', tired face'],['😬','grimacing',', grimacing face'],['😭','sob',', loudly crying face'],['😮','open_mouth',', face with open mouth'],['😯','hushed',', hushed face'],['😰','cold_sweat',', anxious face with sweat'],['😱','scream',', face screaming in fear'],['😲','astonished',', astonished face'],['😳','flushed',', flushed face'],['😴','sleeping',', sleeping face'],['😵','dizzy_face',', dizzy face'],['😶','no_mouth',', face without mouth'],['😷','mask',', face with medical mask'],['😸','smile_cat',', grinning cat with smiling eyes'],['😹','joy_cat',', cat with tears of joy'],['😺','smiley_cat','grinning cat, kitty'],['😻','heart_eyes_cat',', smiling cat with heart-eyes'],['😼','smirk_cat',', cat with wry smile'],['😽','kissing_cat',', kissing cat'],['😾','pouting_cat',', pouting cat'],['😿','crying_cat_face',', crying cat'],['🙀','scream_cat',', weary cat'],['🙁','slight_frown',', slightly frowning face'],['🙂','slight_smile',', slightly smiling face'],['🙃','upside_down',', upside-down face'],['🙄','rolling_eyes',', face with rolling eyes'],['🙅','person_gesturing_no',', person gesturing NO'],['🙆','person_gesturing_ok',', person gesturing OK'],['🙇','person_bowing',', person bowing'],['🙈','see_no_evil',', see-no-evil monkey'],['🙉','hear_no_evil',', hear-no-evil monkey'],['🙊','speak_no_evil',', speak-no-evil monkey'],['🙋','person_raising_hand',', person raising hand'],['🙌','raised_hands',', raising hands'],['🙍','person_frowning',', person frowning'],['🙎','person_pouting',', person pouting'],['🙏','pray',', folded hands'],['🚀','rocket',', rocket'],['🚁','helicopter',', helicopter'],['🚂','steam_locomotive',', locomotive'],['🚃','railway_car',', railway car'],['🚄','bullettrain_side',', high-speed train'],['🚅','bullettrain_front',', bullet train'],['🚆','train2',', train'],['🚇','metro',', metro'],['🚈','light_rail',', light rail'],['🚉','station',', station'],['🚊','tram',', tram'],['🚋','train',', tram car'],['🚌','bus',', bus'],['🚍','oncoming_bus',', oncoming bus'],['🚎','trolleybus',', trolleybus'],['🚏','busstop',', bus stop'],['🚐','minibus',', minibus'],['🚑','ambulance',', ambulance'],['🚒','fire_engine',', fire engine'],['🚓','police_car',', police car'],['🚔','oncoming_police_car',', oncoming police car'],['🚕','taxi',', taxi'],['🚖','oncoming_taxi',', oncoming taxi'],['🚗','red_car',', automobile'],['🚘','oncoming_automobile',', oncoming automobile'],['🚙','blue_car',', sport utility vehicle'],['🚚','truck',', delivery truck'],['🚛','articulated_lorry',', articulated lorry'],['🚜','tractor',', tractor'],['🚝','monorail',', monorail'],['🚞','mountain_railway',', mountain railway'],['🚟','suspension_railway',', suspension railway'],['🚠','mountain_cableway',', mountain cableway'],['🚡','aerial_tramway',', aerial tramway'],['🚢','ship',', ship'],['🚣','person_rowing_boat',', person rowing boat'],['🚤','speedboat',', speedboat'],['🚥','traffic_light',', horizontal traffic light'],['🚦','vertical_traffic_light',', vertical traffic light'],['🚧','construction',', construction'],['🚨','rotating_light',', police car light'],['🚩','triangular_flag_on_post',', triangular flag'],['🚪','door',', door'],['🚫','no_entry_sign',', prohibited'],['🚬','smoking',', cigarette'],['🚭','no_smoking',', no smoking'],['🚮','put_litter_in_its_place',', litter in bin sign'],['🚯','do_not_litter',', no littering'],['🚰','potable_water',', potable water'],['🚱','non-potable_water',', non-potable water'],['🚲','bike',', bicycle'],['🚳','no_bicycles',', no bicycles'],['🚴','person_biking',', person biking'],['🚵','person_mountain_biking',', person mountain biking'],['🚶','person_walking',', person walking'],['🚷','no_pedestrians',', no pedestrians'],['🚸','children_crossing',', children crossing'],['🚹','mens',', men’s room'],['🚺','womens',', women’s room'],['🚻','restroom',', restroom'],['🚼','baby_symbol',', baby symbol'],['🚽','toilet',', toilet'],['🚾','wc',', water closet'],['🚿','shower',', shower'],['🛀','bath',', person taking bath'],['🛁','bathtub',', bathtub'],['🛂','passport_control',', passport control'],['🛃','customs',', customs'],['🛄','baggage_claim',', baggage claim'],['🛅','left_luggage',', left luggage'],['🛌','sleeping_accommodation',', person in bed'],['🛐','place_of_worship',', place of worship'],['🛫','airplane_departure',', airplane departure'],['🛬','airplane_arriving',', airplane arrival'],['🤐','zipper_mouth',', zipper-mouth face'],['🤑','money_mouth',', money-mouth face'],['🤒','thermometer_face',', face with thermometer'],['🤓','nerd',', nerd face'],['🤔','thinking',', thinking face'],['🤕','head_bandage',', face with head-bandage'],['🤖','robot','robot, electronics, AI, artificial intelligence, tech, technology'],['🤗','hugging','hugging face, AI, artificial intelligence'],['🤘','metal','hand, rock, sign of the horns'],['🦀','crab','sea creature, crab, animal, sea, seafood'],['🦁','lion_face','animal, lion'],['🦂','scorpion','animal, scorpion'],['🦃','turkey','turkey, bird,, thanksgiving'],['🦄','unicorn','magic, fantasy, rainbow, unicorn'],['🧀','cheese','food, mouse, cheese wedge'],['🇦🇨','flag_ac','flags, flag: Ascension Island, flag'],['🇦🇩','flag_ad','flag: Andorra, flags, flag'],['🇦🇪','flag_ae','flags, flag: United Arab Emirates, flag'],['🇦🇫','flag_af','flags, flag, flag: Afghanistan'],['🇦🇬','flag_ag','flag: Antigua & Barbuda, flags, flag'],['🇦🇮','flag_ai','flags, flag, flag: Anguilla'],['🇦🇱','flag_al','flag: Albania, flags, flag'],['🇦🇲','flag_am','flags, flag: Armenia, flag'],['🇦🇴','flag_ao','flags, flag, flag: Angola'],['🇦🇶','flag_aq','flag: Antarctica, flags, flag'],['🇦🇷','flag_ar','flags, flag: Argentina, flag'],['🇦🇸','flag_as','flags, flag: American Samoa, flag'],['🇦🇹','flag_at','flags, flag, flag: Austria'],['🇦🇺','flag_au','flags, flag, flag: Australia'],['🇦🇼','flag_aw','flag: Aruba, flags, flag'],['🇦🇽','flag_ax','flag: Åland Islands, flags, flag'],['🇦🇿','flag_az','flags, flag, flag: Azerbaijan'],['🇧🇦','flag_ba','flag: Bosnia & Herzegovina, flags, flag'],['🇧🇧','flag_bb','flag: Barbados, flags, flag'],['🇧🇩','flag_bd','flags, flag, flag: Bangladesh'],['🇧🇪','flag_be','flags, flag, flag: Belgium'],['🇧🇫','flag_bf','flags, flag: Burkina Faso, flag'],['🇧🇬','flag_bg','flag: Bulgaria, flags, flag'],['🇧🇭','flag_bh','flags, flag: Bahrain, flag'],['🇧🇮','flag_bi','flag: Burundi, flags, flag'],['🇧🇯','flag_bj','flag: Benin, flags, flag'],['🇧🇱','flag_bl','flags, flag: St. Barthélemy, flag'],['🇧🇲','flag_bm','flags, flag: Bermuda, flag'],['🇧🇳','flag_bn','flags, flag: Brunei, flag'],['🇧🇴','flag_bo','flag: Bolivia, flags, flag'],['🇧🇶','flag_bq','flags, flag: Caribbean Netherlands, flag'],['🇧🇷','flag_br','flag: Brazil, flags, flag'],['🇧🇸','flag_bs','flag: Bahamas, flags, flag'],['🇧🇹','flag_bt','flags, flag: Bhutan, flag'],['🇧🇻','flag_bv','flag: Bouvet Island, flags, flag'],['🇧🇼','flag_bw','flags, flag, flag: Botswana'],['🇧🇾','flag_by','flags, flag, flag: Belarus'],['🇧🇿','flag_bz','flag: Belize, flags, flag'],['🇨🇦','flag_ca','flag: Canada, flags, flag'],['🇨🇨','flag_cc','flags, flag: Cocos (Keeling) Islands, flag'],['🇨🇩','flag_cd','flag: Congo - Kinshasa, flags, flag'],['🇨🇫','flag_cf','flag: Central African Republic, flags, flag'],['🇨🇬','flag_cg','flags, flag: Congo - Brazzaville, flag'],['🇨🇭','flag_ch','flags, flag: Switzerland, flag'],['🇨🇮','flag_ci','flags, flag: Côte d’Ivoire, flag'],['🇨🇰','flag_ck','flag: Cook Islands, flags, flag'],['🇨🇱','flag_cl','flag: Chile, flags, flag'],['🇨🇲','flag_cm','flag: Cameroon, flags, flag'],['🇨🇳','flag_cn','flags, flag, flag: China'],['🇨🇴','flag_co','flags, flag: Colombia, flag'],['🇨🇵','flag_cp','flags, flag, flag: Clipperton Island'],['🇨🇷','flag_cr','flag: Costa Rica, flags, flag'],['🇨🇺','flag_cu','flag: Cuba, flags, flag'],['🇨🇻','flag_cv','flags, flag: Cape Verde, flag'],['🇨🇼','flag_cw','flag: Curaçao, flags, flag'],['🇨🇽','flag_cx','flags, flag: Christmas Island, flag'],['🇨🇾','flag_cy','flags, flag: Cyprus, flag'],['🇨🇿','flag_cz','flags, flag, flag: Czechia'],['🇩🇪','flag_de','flags, flag, flag: Germany'],['🇩🇬','flag_dg','flag: Diego Garcia, flags, flag'],['🇩🇯','flag_dj','flag: Djibouti, flags, flag'],['🇩🇰','flag_dk','flags, flag, flag: Denmark'],['🇩🇲','flag_dm','flags, flag: Dominica, flag'],['🇩🇴','flag_do','flags, flag: Dominican Republic, flag'],['🇩🇿','flag_dz','flag: Algeria, flags, flag'],['🇪🇦','flag_ea','flags, flag: Ceuta & Melilla, flag'],['🇪🇨','flag_ec','flag: Ecuador, flags, flag'],['🇪🇪','flag_ee','flags, flag, flag: Estonia'],['🇪🇬','flag_eg','flag: Egypt, flags, flag'],['🇪🇭','flag_eh','flags, flag: Western Sahara, flag'],['🇪🇷','flag_er','flags, flag, flag: Eritrea'],['🇪🇸','flag_es','flags, flag: Spain, flag'],['🇪🇹','flag_et','flags, flag: Ethiopia, flag'],['🇪🇺','flag_eu','flags, flag: European Union, flag'],['🇫🇮','flag_fi','flag: Finland, flags, flag'],['🇫🇯','flag_fj','flags, flag, flag: Fiji'],['🇫🇰','flag_fk','flags, flag: Falkland Islands, flag'],['🇫🇲','flag_fm','flags, flag: Micronesia, flag'],['🇫🇴','flag_fo','flags, flag: Faroe Islands, flag'],['🇫🇷','flag_fr','flag: France, flags, flag'],['🇬🇦','flag_ga','flags, flag: Gabon, flag'],['🇬🇧','flag_gb','flag: United Kingdom, flags, flag'],['🇬🇩','flag_gd','flag: Grenada, flags, flag'],['🇬🇪','flag_ge','flags, flag, flag: Georgia'],['🇬🇫','flag_gf','flags, flag, flag: French Guiana'],['🇬🇬','flag_gg','flag: Guernsey, flags, flag'],['🇬🇭','flag_gh','flag: Ghana, flags, flag'],['🇬🇮','flag_gi','flags, flag, flag: Gibraltar'],['🇬🇱','flag_gl','flags, flag: Greenland, flag'],['🇬🇲','flag_gm','flag: Gambia, flags, flag'],['🇬🇳','flag_gn','flags, flag: Guinea, flag'],['🇬🇵','flag_gp','flags, flag: Guadeloupe, flag'],['🇬🇶','flag_gq','flags, flag, flag: Equatorial Guinea'],['🇬🇷','flag_gr','flag: Greece, flags, flag'],['🇬🇸','flag_gs','flag: South Georgia & South Sandwich Islands, flags, flag'],['🇬🇹','flag_gt','flags, flag: Guatemala, flag'],['🇬🇺','flag_gu','flag: Guam, flags, flag'],['🇬🇼','flag_gw','flag: Guinea-Bissau, flags, flag'],['🇬🇾','flag_gy','flag: Guyana, flags, flag'],['🇭🇰','flag_hk','flag: Hong Kong SAR China, flags, flag'],['🇭🇲','flag_hm','flags, flag, flag: Heard & McDonald Islands'],['🇭🇳','flag_hn','flags, flag, flag: Honduras'],['🇭🇷','flag_hr','flags, flag: Croatia, flag'],['🇭🇹','flag_ht','flags, flag: Haiti, flag'],['🇭🇺','flag_hu','flags, flag: Hungary, flag'],['🇮🇨','flag_ic','flags, flag, flag: Canary Islands'],['🇮🇩','flag_id','flags, flag: Indonesia, flag'],['🇮🇪','flag_ie','flags, flag: Ireland, flag'],['🇮🇱','flag_il','flags, flag: Israel, flag'],['🇮🇲','flag_im','flag: Isle of Man, flags, flag'],['🇮🇳','flag_in','flags, flag, flag: India'],['🇮🇴','flag_io','flags, flag: British Indian Ocean Territory, flag'],['🇮🇶','flag_iq','flag: Iraq, flags, flag'],['🇮🇷','flag_ir','flags, flag, flag: Iran'],['🇮🇸','flag_is','flags, flag: Iceland, flag'],['🇮🇹','flag_it','flags, flag: Italy, flag'],['🇯🇪','flag_je','flags, flag, flag: Jersey'],['🇯🇲','flag_jm','flags, flag, flag: Jamaica'],['🇯🇴','flag_jo','flag: Jordan, flags, flag'],['🇯🇵','flag_jp','flags, flag: Japan, flag'],['🇰🇪','flag_ke','flag: Kenya, flags, flag'],['🇰🇬','flag_kg','flag: Kyrgyzstan, flags, flag'],['🇰🇭','flag_kh','flag: Cambodia, flags, flag'],['🇰🇮','flag_ki','flag: Kiribati, flags, flag'],['🇰🇲','flag_km','flags, flag, flag: Comoros'],['🇰🇳','flag_kn','flags, flag: St. Kitts & Nevis, flag'],['🇰🇵','flag_kp','flag: North Korea, flags, flag'],['🇰🇷','flag_kr','flags, flag: South Korea, flag'],['🇰🇼','flag_kw','flags, flag, flag: Kuwait'],['🇰🇾','flag_ky','flags, flag: Cayman Islands, flag'],['🇰🇿','flag_kz','flags, flag: Kazakhstan, flag'],['🇱🇦','flag_la','flags, flag, flag: Laos'],['🇱🇧','flag_lb','flags, flag, flag: Lebanon'],['🇱🇨','flag_lc','flag: St. Lucia, flags, flag'],['🇱🇮','flag_li','flags, flag, flag: Liechtenstein'],['🇱🇰','flag_lk','flags, flag, flag: Sri Lanka'],['🇱🇷','flag_lr','flag: Liberia, flags, flag'],['🇱🇸','flag_ls','flag: Lesotho, flags, flag'],['🇱🇹','flag_lt','flags, flag: Lithuania, flag'],['🇱🇺','flag_lu','flags, flag, flag: Luxembourg'],['🇱🇻','flag_lv','flag: Latvia, flags, flag'],['🇱🇾','flag_ly','flags, flag: Libya, flag'],['🇲🇦','flag_ma','flags, flag, flag: Morocco'],['🇲🇨','flag_mc','flags, flag, flag: Monaco'],['🇲🇩','flag_md','flag: Moldova, flags, flag'],['🇲🇪','flag_me','flag: Montenegro, flags, flag'],['🇲🇫','flag_mf','flags, flag, flag: St. Martin'],['🇲🇬','flag_mg','flags, flag, flag: Madagascar'],['🇲🇭','flag_mh','flags, flag: Marshall Islands, flag'],['🇲🇰','flag_mk','flags, flag, flag: North Macedonia'],['🇲🇱','flag_ml','flag: Mali, flags, flag'],['🇲🇲','flag_mm','flags, flag: Myanmar (Burma), flag'],['🇲🇳','flag_mn','flag: Mongolia, flags, flag'],['🇲🇴','flag_mo','flags, flag: Macao SAR China, flag'],['🇲🇵','flag_mp','flags, flag: Northern Mariana Islands, flag'],['🇲🇶','flag_mq','flags, flag: Martinique, flag'],['🇲🇷','flag_mr','flag: Mauritania, flags, flag'],['🇲🇸','flag_ms','flags, flag, flag: Montserrat'],['🇲🇹','flag_mt','flags, flag: Malta, flag'],['🇲🇺','flag_mu','flags, flag, flag: Mauritius'],['🇲🇻','flag_mv','flag: Maldives, flags, flag'],['🇲🇼','flag_mw','flags, flag: Malawi, flag'],['🇲🇽','flag_mx','flag: Mexico, flags, flag'],['🇲🇾','flag_my','flags, flag: Malaysia, flag'],['🇲🇿','flag_mz','flags, flag: Mozambique, flag'],['🇳🇦','flag_na','flags, flag, flag: Namibia'],['🇳🇨','flag_nc','flags, flag, flag: New Caledonia'],['🇳🇪','flag_ne','flags, flag: Niger, flag'],['🇳🇫','flag_nf','flags, flag, flag: Norfolk Island'],['🇳🇬','flag_ng','flags, flag: Nigeria, flag'],['🇳🇮','flag_ni','flags, flag: Nicaragua, flag'],['🇳🇱','flag_nl','flags, flag, flag: Netherlands'],['🇳🇴','flag_no','flag: Norway, flags, flag'],['🇳🇵','flag_np','flags, flag, flag: Nepal'],['🇳🇷','flag_nr','flags, flag: Nauru, flag'],['🇳🇺','flag_nu','flag: Niue, flags, flag'],['🇳🇿','flag_nz','flag: New Zealand, flags, flag'],['🇴🇲','flag_om','flags, flag: Oman, flag'],['🇵🇦','flag_pa','flags, flag, flag: Panama'],['🇵🇪','flag_pe','flag: Peru, flags, flag'],['🇵🇫','flag_pf','flag: French Polynesia, flags, flag'],['🇵🇬','flag_pg','flags, flag: Papua New Guinea, flag'],['🇵🇭','flag_ph','flags, flag, flag: Philippines'],['🇵🇰','flag_pk','flag: Pakistan, flags, flag'],['🇵🇱','flag_pl','flags, flag: Poland, flag'],['🇵🇲','flag_pm','flags, flag, flag: St. Pierre & Miquelon'],['🇵🇳','flag_pn','flags, flag, flag: Pitcairn Islands'],['🇵🇷','flag_pr','flag: Puerto Rico, flags, flag'],['🇵🇸','flag_ps','flags, flag: Palestinian Territories, flag'],['🇵🇹','flag_pt','flag: Portugal, flags, flag'],['🇵🇼','flag_pw','flag: Palau, flags, flag'],['🇵🇾','flag_py','flag: Paraguay, flags, flag'],['🇶🇦','flag_qa','flag: Qatar, flags, flag'],['🇷🇪','flag_re','flags, flag, flag: Réunion'],['🇷🇴','flag_ro','flags, flag, flag: Romania'],['🇷🇸','flag_rs','flags, flag: Serbia, flag'],['🇷🇺','flag_ru','flags, flag, flag: Russia'],['🇷🇼','flag_rw','flags, flag, flag: Rwanda'],['🇸🇦','flag_sa','flags, flag, flag: Saudi Arabia'],['🇸🇧','flag_sb','flag: Solomon Islands, flags, flag'],['🇸🇨','flag_sc','flags, flag: Seychelles, flag'],['🇸🇩','flag_sd','flags, flag, flag: Sudan'],['🇸🇪','flag_se','flag: Sweden, flags, flag'],['🇸🇬','flag_sg','flags, flag, flag: Singapore'],['🇸🇭','flag_sh','flags, flag, flag: St. Helena'],['🇸🇮','flag_si','flags, flag: Slovenia, flag'],['🇸🇯','flag_sj','flag: Svalbard & Jan Mayen, flags, flag'],['🇸🇰','flag_sk','flags, flag, flag: Slovakia'],['🇸🇱','flag_sl','flag: Sierra Leone, flags, flag'],['🇸🇲','flag_sm','flags, flag: San Marino, flag'],['🇸🇳','flag_sn','flags, flag: Senegal, flag'],['🇸🇴','flag_so','flags, flag, flag: Somalia'],['🇸🇷','flag_sr','flag: Suriname, flags, flag'],['🇸🇸','flag_ss','flags, flag: South Sudan, flag'],['🇸🇹','flag_st','flags, flag: São Tomé & Príncipe, flag'],['🇸🇻','flag_sv','flags, flag: El Salvador, flag'],['🇸🇽','flag_sx','flags, flag, flag: Sint Maarten'],['🇸🇾','flag_sy','flags, flag: Syria, flag'],['🇸🇿','flag_sz','flags, flag: Eswatini, flag'],['🇹🇦','flag_ta','flags, flag: Tristan da Cunha, flag'],['🇹🇨','flag_tc','flags, flag, flag: Turks & Caicos Islands'],['🇹🇩','flag_td','flags, flag: Chad, flag'],['🇹🇫','flag_tf','flag: French Southern Territories, flags, flag'],['🇹🇬','flag_tg','flags, flag, flag: Togo'],['🇹🇭','flag_th','flag: Thailand, flags, flag'],['🇹🇯','flag_tj','flag: Tajikistan, flags, flag'],['🇹🇰','flag_tk','flags, flag: Tokelau, flag'],['🇹🇱','flag_tl','flags, flag: Timor-Leste, flag'],['🇹🇲','flag_tm','flags, flag, flag: Turkmenistan'],['🇹🇳','flag_tn','flag: Tunisia, flags, flag'],['🇹🇴','flag_to','flags, flag, flag: Tonga'],['🇹🇷','flag_tr','flags, flag: Turkey, flag'],['🇹🇹','flag_tt','flags, flag, flag: Trinidad & Tobago'],['🇹🇻','flag_tv','flag: Tuvalu, flags, flag'],['🇹🇼','flag_tw','flag: Taiwan, flags, flag'],['🇹🇿','flag_tz','flag: Tanzania, flags, flag'],['🇺🇦','flag_ua','flags, flag, flag: Ukraine'],['🇺🇬','flag_ug','flags, flag: Uganda, flag'],['🇺🇲','flag_um','flags, flag, flag: U.S. Outlying Islands'],['🇺🇸','flag_us','flags, flag, flag: United States'],['🇺🇾','flag_uy','flags, flag, flag: Uruguay'],['🇺🇿','flag_uz','flags, flag, flag: Uzbekistan'],['🇻🇦','flag_va','flags, flag: Vatican City, flag'],['🇻🇨','flag_vc','flag: St. Vincent & Grenadines, flags, flag'],['🇻🇪','flag_ve','flags, flag, flag: Venezuela'],['🇻🇬','flag_vg','flag: British Virgin Islands, flags, flag'],['🇻🇮','flag_vi','flag: U.S. Virgin Islands, flags, flag'],['🇻🇳','flag_vn','flags, flag: Vietnam, flag'],['🇻🇺','flag_vu','flags, flag: Vanuatu, flag'],['🇼🇫','flag_wf','flag: Wallis & Futuna, flags, flag'],['🇼🇸','flag_ws','flag: Samoa, flags, flag'],['🇽🇰','flag_xk','flags, flag, flag: Kosovo'],['🇾🇪','flag_ye','flags, flag, flag: Yemen'],['🇾🇹','flag_yt','flags, flag, flag: Mayotte'],['🇿🇦','flag_za','flags, flag: South Africa, flag'],['🇿🇲','flag_zm','flags, flag: Zambia, flag'],['🇿🇼','flag_zw','flags, flag: Zimbabwe, flag'],['🏳️‍🌈','rainbow_flag','flag, rainbow flag, pride, gay, flags'],['🏳️‍⚧️','transgender_flag','trans, pride, flag, flags']];} \ No newline at end of file From 473698c74480a0d57d8abe956325edb40e2d5482 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Mon, 3 Mar 2025 23:36:34 +0100 Subject: [PATCH 016/127] Refactor split view styles and update theme variables for improved UI consistency --- src/browser/app/profile/zen-browser.js | 2 +- .../base/content/zen-styles/zen-decks.css | 75 +++++--- .../content/zen-styles/zen-sidebar-panels.css | 2 +- .../base/content/zen-styles/zen-theme.css | 2 +- .../base/zen-components/ZenViewSplitter.mjs | 160 ++++++++++-------- src/browser/themes/shared/zen-icons/icons.css | 7 +- .../PictureInPicture-sys-mjs.patch | 12 +- 7 files changed, 165 insertions(+), 95 deletions(-) diff --git a/src/browser/app/profile/zen-browser.js b/src/browser/app/profile/zen-browser.js index 630930c8c..7e038cf30 100644 --- a/src/browser/app/profile/zen-browser.js +++ b/src/browser/app/profile/zen-browser.js @@ -379,7 +379,7 @@ pref('widget.macos.titlebar-blend-mode.behind-window', true); // 5. toolTip // 6. headerView // 7. underlay -pref('zen.widget.macos.window-material', 7); +pref('zen.widget.macos.window-material', 1); #endif // Urlbar and autocomplete diff --git a/src/browser/base/content/zen-styles/zen-decks.css b/src/browser/base/content/zen-styles/zen-decks.css index f94dd5899..40bc938eb 100644 --- a/src/browser/base/content/zen-styles/zen-decks.css +++ b/src/browser/base/content/zen-styles/zen-decks.css @@ -45,8 +45,7 @@ } #tabbrowser-tabpanels[zen-split-view='true'] .browserSidebarContainer.deck-selected { - outline: 2px solid var(--zen-primary-color) !important; - outline-offset: -1px; + outline: 1px solid var(--zen-primary-color) !important; } #tabbrowser-tabbox:has(#tabbrowser-tabpanels[zen-split-view='true']) { @@ -214,38 +213,69 @@ display: revert; } -.zen-view-splitter-header { - display: flex; - width: 100%; - height: 20px; - /*TODO: update with appropriate color*/ - background-color: var(--zen-colors-secondary); - align-items: center; +.zen-view-splitter-header-container { + position: absolute; + top: calc(var(--zen-split-column-gap) / -2); + left: 50%; + opacity: 0; + transition: opacity 0.2s; z-index: 100; - cursor: move; + transform: translateX(-50%); + pointer-events: none; + + &::before { + content: ''; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 100%; + height: 6px; + background: var(--zen-colors-border); + } } -.zen-tab-unsplit-button { +.zen-view-splitter-header { + display: flex; + align-items: center; + position: fixed; + padding: 0.4rem 0.6rem; + border-radius: 8px; + background-color: light-dark(rgba(255, 255, 255, 1), rgba(0, 0, 0, 1)); + box-shadow: 0 0 0 1px var(--button-primary-border-color); + gap: 0.8rem; +} + +:root:not([inDOMFullscreen='true']) .browserSidebarContainer:hover .zen-view-splitter-header-container, +.zen-view-splitter-header-container:hover { + pointer-events: all; + opacity: 1; + transition-delay: 0.2s; +} + +.zen-view-splitter-header-container toolbarbutton { display: block; -moz-context-properties: fill, fill-opacity; border-radius: var(--tab-border-radius); - /*TODO: update with appropriate color*/ color: inherit; fill: currentColor; - padding: var(--tab-close-button-padding); - width: 24px; - height: 24px; + width: 16px; + height: 16px; cursor: pointer; appearance: none; - margin-left: auto; - outline: var(--toolbarbutton-outline); - list-style-image: url('chrome://global/skin/icons/close-fill.svg') !important; - &:hover { - outline-color: var(--toolbarbutton-hover-outline-color); + outline: none; + color: var(--button-primary-color); + border-top-left-radius: 0; + border-top-right-radius: 0; + + & image { + width: 14px; + height: 14px; } - &:hover:active { - outline-color: var(--toolbarbutton-active-outline-color); + &.zen-tab-rearrange-button image { + transform: rotate(90deg); + cursor: move; } } @@ -264,6 +294,7 @@ left: 50%; transform: translate(-50%, -50%); width: 3.5rem; + pointer-events: none; height: 3.5rem; background: var(--zen-split-view-fake-icon); background-size: contain; diff --git a/src/browser/base/content/zen-styles/zen-sidebar-panels.css b/src/browser/base/content/zen-styles/zen-sidebar-panels.css index 9faed1712..a7cb968b5 100644 --- a/src/browser/base/content/zen-styles/zen-sidebar-panels.css +++ b/src/browser/base/content/zen-styles/zen-sidebar-panels.css @@ -122,7 +122,7 @@ &::before { height: 50px; width: 4px; - background: var(--zen-colors-primary); + background: var(--button-primary-bgcolor); border-radius: 2px; content: ''; position: absolute; diff --git a/src/browser/base/content/zen-styles/zen-theme.css b/src/browser/base/content/zen-styles/zen-theme.css index d15c7eef0..9dfcc3d99 100644 --- a/src/browser/base/content/zen-styles/zen-theme.css +++ b/src/browser/base/content/zen-styles/zen-theme.css @@ -164,7 +164,7 @@ background: transparent; --zen-themed-toolbar-bg-transparent: transparent; @media (-moz-bool-pref: 'zen.widget.windows.acrylic') { - --zen-themed-toolbar-bg-transparent: color-mix(in srgb, var(--zen-themed-toolbar-bg) 80%, transparent 20%); + --zen-themed-toolbar-bg-transparent: color-mix(in srgb, var(--zen-themed-toolbar-bg) 75%, transparent 25%); } } diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index f04e865e2..ff05f066c 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -177,13 +177,21 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { } draggedTab.container._finishMoveTogetherSelectedTabs(draggedTab); } - if (!draggedTab || this._canDrop || this._hasAnimated || this.fakeBrowser || !this._lastOpenedTab) { + if ( + !draggedTab || + this._canDrop || + this._hasAnimated || + this.fakeBrowser || + !this._lastOpenedTab || + (this._lastOpenedTab && + this._lastOpenedTab.getAttribute('zen-workspace-id') !== draggedTab.getAttribute('zen-workspace-id')) + ) { return; } if (draggedTab.splitView) { return; } - const currentView = this._data[this.currentView]; + const currentView = this._data[this._lastOpenedTab.splitViewValue]; if (currentView?.tabs.length >= this.MAX_TABS) { return; } @@ -249,48 +257,46 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { if (!this._hasAnimated || !this.fakeBrowser) { return; } - setTimeout(() => { - const panelsWidth = panelsRect.width; - const halfWidth = panelsWidth / 2; - const padding = Services.prefs.getIntPref('zen.theme.content-element-separation', 0); - if (!this.fakeBrowser) { - return; - } - this.fakeBrowser.classList.add('fade-out'); - gBrowser.selectedTab = this._draggingTab; - this._draggingTab = null; - try { - Promise.all([ - gZenUIManager.motion.animate( - gBrowser.tabbox, - { - paddingLeft: [`${halfWidth}px`, 0], - }, - { - duration: 0.15, - easing: 'ease-out', - } - ), - gZenUIManager.motion.animate( - this.fakeBrowser, - { - width: [`${halfWidth - padding * 2}px`, 0], - marginLeft: [`${-(halfWidth - padding)}px`, 0], - }, - { - duration: 0.15, - easing: 'ease-out', - } - ), - ]).then(() => { - this._canDrop = false; - this._maybeRemoveFakeBrowser(); - }); - } catch (e) { + const panelsWidth = panelsRect.width; + const halfWidth = panelsWidth / 2; + const padding = Services.prefs.getIntPref('zen.theme.content-element-separation', 0); + if (!this.fakeBrowser) { + return; + } + this.fakeBrowser.classList.add('fade-out'); + gBrowser.selectedTab = this._draggingTab; + this._draggingTab = null; + try { + Promise.all([ + gZenUIManager.motion.animate( + gBrowser.tabbox, + { + paddingLeft: [`${halfWidth}px`, 0], + }, + { + duration: 0.15, + easing: 'ease-out', + } + ), + gZenUIManager.motion.animate( + this.fakeBrowser, + { + width: [`${halfWidth - padding * 2}px`, 0], + marginLeft: [`${-(halfWidth - padding)}px`, 0], + }, + { + duration: 0.15, + easing: 'ease-out', + } + ), + ]).then(() => { this._canDrop = false; this._maybeRemoveFakeBrowser(); - } - }, 100); + }); + } catch (e) { + this._canDrop = false; + this._maybeRemoveFakeBrowser(); + } } /** @@ -440,7 +446,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { let isSplitHeaderDrag = false; const container = event.target.closest('.browserSidebarContainer[zen-split]'); - if (container && event.offsetY < 20) { + if (container && event.target.closest('.zen-tab-rearrange-button')) { // Split tab header drag case const containerRect = container.getBoundingClientRect(); const clickX = event.clientX - containerRect.left; @@ -700,6 +706,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { */ resetTabState(tab, forUnsplit) { tab.splitView = false; + delete tab.splitViewValue; tab.removeAttribute('split-view'); tab.linkedBrowser.zenModeActive = false; const container = tab.linkedBrowser.closest('.browserSidebarContainer'); @@ -853,6 +860,26 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { this._maybeRemoveFakeBrowser(); } + /** + * @param {Tab} tab + */ + _moveTabsToContainer(tabs, relativeTab) { + const relativeTabIsPinned = relativeTab.pinned; + const relativeTabIsEssential = relativeTab.hasAttribute('zen-essential'); + + if (relativeTabIsEssential) { + gZenPinnedTabManager.addToEssentials(tabs); + } else { + for (const tab of tabs) { + if (relativeTabIsPinned) { + gBrowser.pinTab(tab); + } else { + gBrowser.unpinTab(tab); + } + } + } + } + /** * Splits the given tabs. * @@ -865,20 +892,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { if (tabs.length < 2 || tabs.length > this.MAX_TABS) { return; } - const firstIsPinned = tabs[initialIndex].pinned; - const firstIsEssential = tabs[initialIndex].hasAttribute('zen-essential'); - const oddOnes = tabs.filter((t) => t.pinned !== firstIsPinned || t.hasAttribute('zen-essential') != firstIsEssential); - if (firstIsEssential) { - gZenPinnedTabManager.addToEssentials(oddOnes); - } else { - for (const tab of oddOnes) { - if (firstIsPinned) { - gBrowser.pinTab(tab); - } else { - gBrowser.unpinTab(tab); - } - } - } + this._moveTabsToContainer(tabs, tabs[initialIndex]); const existingSplitTab = tabs.find((tab) => tab.splitView); if (existingSplitTab) { @@ -1025,9 +1039,10 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { applyGridToTabs(tabs) { tabs.forEach((tab, index) => { tab.splitView = true; + tab.splitViewValue = this.currentView; tab.setAttribute('split-view', 'true'); - const container = tab.linkedBrowser.closest('.browserContainer'); - if (!container.querySelector('.zen-view-splitter-header')) { + const container = tab.linkedBrowser?.closest('.browserSidebarContainer'); + if (!container?.querySelector('.zen-tab-rearrange-button')) { // insert a header into the container const header = this._createHeader(container); container.insertBefore(header, container.firstChild); @@ -1043,6 +1058,8 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { * @private */ _createHeader(container) { + const headerContainer = document.createElement('div'); + headerContainer.classList.add('zen-view-splitter-header-container'); const header = document.createElement('div'); header.classList.add('zen-view-splitter-header'); const removeButton = document.createXULElement('toolbarbutton'); @@ -1050,12 +1067,16 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { removeButton.addEventListener('click', () => { this.removeTabFromSplit(container); }); + const rearrangeButton = document.createXULElement('toolbarbutton'); + rearrangeButton.classList.add('zen-tab-rearrange-button'); + header.appendChild(rearrangeButton); header.appendChild(removeButton); - return header; + headerContainer.appendChild(header); + return headerContainer; } _removeHeader(container) { - const header = container.querySelector('.zen-view-splitter-header'); + const header = container.querySelector('.zen-view-splitter-header-container'); if (header) { header.remove(); } @@ -1446,14 +1467,16 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { } }; - _maybeRemoveFakeBrowser() { + _maybeRemoveFakeBrowser(select = true) { gBrowser.tabbox.removeAttribute('style'); if (this.fakeBrowser) { delete this._hasAnimated; this.fakeBrowser.remove(); this.fakeBrowser = null; - gBrowser.selectedTab = this._draggingTab; - this._draggingTab = null; + if (select) { + gBrowser.selectedTab = this._draggingTab; + this._draggingTab = null; + } } } @@ -1465,7 +1488,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { */ moveTabToSplitView(event, draggedTab) { const canDrop = this._canDrop; - this._maybeRemoveFakeBrowser(); + this._maybeRemoveFakeBrowser(false); this._canDrop = false; if (!canDrop) { return false; @@ -1474,6 +1497,9 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { const dropTarget = document.elementFromPoint(event.clientX, event.clientY); const browser = dropTarget?.closest('browser'); + gBrowser.selectedTab = this._draggingTab; + this._draggingTab = null; + if (!browser) { return false; } @@ -1482,7 +1508,8 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { if (droppedOnTab && droppedOnTab !== draggedTab) { // Calculate which side of the target browser the drop occurred const browserRect = browser.getBoundingClientRect(); - const hoverSide = this.calculateHoverSide(event.clientX, event.clientY, browserRect); + // const hoverSide = this.calculateHoverSide(event.clientX, event.clientY, browserRect); + const hoverSide = 'right'; if (droppedOnTab.splitView) { // Add to existing split view @@ -1493,6 +1520,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { // First move the tab to the split view group let splitGroup = droppedOnTab.group; if (splitGroup && (!draggedTab.group || draggedTab.group !== splitGroup)) { + this._moveTabsToContainer([draggedTab], droppedOnTab); gBrowser.moveTabToGroup(draggedTab, splitGroup); } diff --git a/src/browser/themes/shared/zen-icons/icons.css b/src/browser/themes/shared/zen-icons/icons.css index 32e8e7838..7c6ff2dca 100644 --- a/src/browser/themes/shared/zen-icons/icons.css +++ b/src/browser/themes/shared/zen-icons/icons.css @@ -23,6 +23,10 @@ list-style-image: url('move-tab.svg') !important; } +.zen-tab-unsplit-button { + list-style-image: url('unpin.svg') !important; +} + #forward-button, #zen-sidebar-web-panel-forward { list-style-image: url('forward.svg') !important; @@ -381,7 +385,8 @@ list-style-image: url('arrow-down.svg') !important; } -.zen-workspace-actions-reorder-icon { +.zen-workspace-actions-reorder-icon, +.zen-tab-rearrange-button { list-style-image: url('drag-indicator.svg') !important; } diff --git a/src/toolkit/components/pictureinpicture/PictureInPicture-sys-mjs.patch b/src/toolkit/components/pictureinpicture/PictureInPicture-sys-mjs.patch index d0a889937..a6be52467 100644 --- a/src/toolkit/components/pictureinpicture/PictureInPicture-sys-mjs.patch +++ b/src/toolkit/components/pictureinpicture/PictureInPicture-sys-mjs.patch @@ -1,8 +1,8 @@ diff --git a/toolkit/components/pictureinpicture/PictureInPicture.sys.mjs b/toolkit/components/pictureinpicture/PictureInPicture.sys.mjs -index 27f7208ac689c51443a0a6ffafd77f89b71d0030..dcd664f85e27618e23118a80af54a6400b12b806 100644 +index 5da0404b2672ba8cce7bcf808bf2373474776654..c3d58941b66c54f9d506698d015e294f8c8a5ceb 100644 --- a/toolkit/components/pictureinpicture/PictureInPicture.sys.mjs +++ b/toolkit/components/pictureinpicture/PictureInPicture.sys.mjs -@@ -471,8 +471,8 @@ export var PictureInPicture = { +@@ -488,13 +488,13 @@ export var PictureInPicture = { return; } @@ -13,7 +13,13 @@ index 27f7208ac689c51443a0a6ffafd77f89b71d0030..dcd664f85e27618e23118a80af54a640 // focus the tab's window tab.ownerGlobal.focus(); -@@ -875,7 +875,7 @@ export var PictureInPicture = { + +- gBrowser.selectedTab = tab; ++ browser?.ownerGlobal?.ZenWorkspaces.switchIfNeeded(browser); + await this.closeSinglePipWindow({ reason: "Unpip", actorRef: pipActor }); + }, + +@@ -877,7 +877,7 @@ export var PictureInPicture = { win.setIsMutedState(videoData.isMuted); // set attribute which shows pip icon in tab From 23a60e79c166824e49c1b26e84bac2a09190f9c6 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Mon, 3 Mar 2025 23:52:09 +0100 Subject: [PATCH 017/127] Update split view tab styles for collapsed mode --- src/browser/base/content/zen-styles/zen-folders.css | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/browser/base/content/zen-styles/zen-folders.css b/src/browser/base/content/zen-styles/zen-folders.css index 29be10fc5..42ef4c01d 100644 --- a/src/browser/base/content/zen-styles/zen-folders.css +++ b/src/browser/base/content/zen-styles/zen-folders.css @@ -14,7 +14,11 @@ tab-group[split-view-group] { --zen-split-view-active-tab-bg: color-mix(in srgb, var(--zen-toolbar-element-bg), transparent 40%); :root:not([zen-sidebar-expanded='true']) & { - padding: 2px 0; + padding: 0 2px; + --tab-min-height: 30px; + --tab-collapsed-width: 38px; + margin: 0 auto; + --tab-min-width: 34px; } & > .tabbrowser-tab { From 096a28002f21d3e973e40079a92d60e3f8320ad0 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Tue, 4 Mar 2025 00:22:40 +0100 Subject: [PATCH 018/127] Refactor compact mode styles and improve tab positioning for better layout consistency --- .../content/zen-styles/zen-compact-mode.css | 11 ++++--- .../base/zen-components/ZenViewSplitter.mjs | 7 +++-- .../themes/shared/tabbrowser/tabs-css.patch | 31 +++++++++++++++++-- 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-compact-mode.css b/src/browser/base/content/zen-styles/zen-compact-mode.css index fa6f2f835..dc7e849b0 100644 --- a/src/browser/base/content/zen-styles/zen-compact-mode.css +++ b/src/browser/base/content/zen-styles/zen-compact-mode.css @@ -54,7 +54,8 @@ opacity: 0; :root[zen-single-toolbar='true'] & { - top: var(--zen-element-separation); + top: calc(var(--zen-element-separation) / 2); + height: calc(100% - var(--zen-element-separation)); } } @@ -254,14 +255,14 @@ 1.003423 100% ); transition: - left 0.3s var(--zen-compact-mode-func), - right 0.3s var(--zen-compact-mode-func); + left 0.25s var(--zen-compact-mode-func), + right 0.25s var(--zen-compact-mode-func); opacity: 1; &:not([supress-primary-adjustment='true']) { - left: -1px; + left: calc(var(--zen-element-separation) / -2); :root[zen-right-side='true'] & { - right: -1px; + right: calc(var(--zen-element-separation) / -2); left: auto; } } diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index ff05f066c..323d31223 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -263,6 +263,10 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { if (!this.fakeBrowser) { return; } + // if we are still in that 1/4 of the way to the edge then we should not hide the fake browser + if (event.clientX < (panelsWidth / 4) * 3 && event.clientX > panelsRect.left) { + return; + } this.fakeBrowser.classList.add('fade-out'); gBrowser.selectedTab = this._draggingTab; this._draggingTab = null; @@ -1507,7 +1511,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { const droppedOnTab = gBrowser.getTabForBrowser(browser); if (droppedOnTab && droppedOnTab !== draggedTab) { // Calculate which side of the target browser the drop occurred - const browserRect = browser.getBoundingClientRect(); + // const browserRect = browser.getBoundingClientRect(); // const hoverSide = this.calculateHoverSide(event.clientX, event.clientY, browserRect); const hoverSide = 'right'; @@ -1567,7 +1571,6 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { draggedTab.linkedBrowser.closest('.browserSidebarContainer'), { scale: [0.98, 1], - opacity: [0, 1], }, { type: 'spring', diff --git a/src/browser/themes/shared/tabbrowser/tabs-css.patch b/src/browser/themes/shared/tabbrowser/tabs-css.patch index 88b266b14..8d7b707e9 100644 --- a/src/browser/themes/shared/tabbrowser/tabs-css.patch +++ b/src/browser/themes/shared/tabbrowser/tabs-css.patch @@ -1,5 +1,5 @@ diff --git a/browser/themes/shared/tabbrowser/tabs.css b/browser/themes/shared/tabbrowser/tabs.css -index 01815c2114a627e5cac183c702bd82f1bd4f58f8..3a453164ee8a555db2a0ba28288d69857a4933bc 100644 +index 01815c2114a627e5cac183c702bd82f1bd4f58f8..ad3686a4bcac0331d86f5e95ecdb6f023b2641bf 100644 --- a/browser/themes/shared/tabbrowser/tabs.css +++ b/browser/themes/shared/tabbrowser/tabs.css @@ -31,7 +31,7 @@ @@ -42,10 +42,37 @@ index 01815c2114a627e5cac183c702bd82f1bd4f58f8..3a453164ee8a555db2a0ba28288d6985 #tabbrowser-tabs[orient=vertical] & { - top: 7px; -+ top: 0px; ++ top: -7px; } &[crashed] { +@@ -510,7 +509,7 @@ + } + + #tabbrowser-tabs[orient="vertical"]:not([expanded]) &:not([crashed]), +- &[pinned]:not([crashed]) { ++ &:not([crashed]) { + &[soundplaying] { + list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-playing-small.svg"); + } +@@ -572,7 +571,7 @@ + } + + #tabbrowser-tabs[orient="vertical"]:not([expanded]) &:is([soundplaying], [muted], [activemedia-blocked]), +- &[pinned]:is([soundplaying], [muted], [activemedia-blocked]), ++ &:is([soundplaying], [muted], [activemedia-blocked]), + &[crashed] { + display: revert; + } +@@ -586,7 +585,7 @@ + --button-min-height-small: 24px; + --button-border-radius: var(--border-radius-small); + +- #tabbrowser-tabs:is([orient="vertical"][expanded], [orient="horizontal"]) &:not([pinned]):not([crashed]) { ++ #tabbrowser-tabs:is([orient="horizontal"]) &:not([pinned]):not([crashed]) { + &:is([soundplaying], [muted], [activemedia-blocked]) { + display: block; + } @@ -617,14 +616,14 @@ } From 1c2ddea3d421a714c379a39c8c00cf8f8af5f8b7 Mon Sep 17 00:00:00 2001 From: Gabriel Fernandes Date: Tue, 4 Mar 2025 10:05:56 +0000 Subject: [PATCH 019/127] fix: remove extra words from martial arts uniform emoji --- src/browser/base/zen-components/ZenEmojies.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/base/zen-components/ZenEmojies.mjs b/src/browser/base/zen-components/ZenEmojies.mjs index a46451bf9..e39dadaac 100644 --- a/src/browser/base/zen-components/ZenEmojies.mjs +++ b/src/browser/base/zen-components/ZenEmojies.mjs @@ -1 +1 @@ -function zenGlobalEmojis() { return [['⌚','watch','watch, clock, time, wristwatch'],['⌛','hourglass','hourglass done, time, sand, clock'],['⏪','rewind','arrow, blue, rewind, fast reverse button, left, back'],['⏫','arrow_double_up','increase, arrow, fast up button, blue, up'],['⏬','arrow_double_down','decrease, down, arrow, blue, fast down button'],['⏰','alarm_clock','alarm clock, clock, alarm, time, red'],['⏳','hourglass_flowing_sand','hourglass not done, time, sand, clock'],['⚽','soccer','sports, football, soccer ball, ball, soccer, soccer ball,'],['⚾','baseball','ball, baseball, sports'],['⛄','snowman','snowman, snowman without snow, christmas, holidays, snow'],['⛅','partly_sunny','sun, sun behind cloud, cloudy, sunny, weather'],['⛎','ophiuchus','zodiac, horoscope, Ophiuchus, purple'],['⛔','no_entry','sign, red, stop, no entry'],['⛪','church','church, building, religion, worship, faith, holy'],['⛲','fountain','fountain, water, garden'],['⛳','golf','sports, golf, flag in hole, flag'],['⛵','sailboat','vessel, vacation, sailing, sea, ship, sailboat, water, boat, travel, ocean'],['⛺','tent','camp, camping, outdoor, tent, camping, shelter, nature, vacation'],['⛽','fuelpump','oil, petrol, fuel pump, gas, red, gas station, fuel'],['✅','white_check_mark','approve, check, check mark, tick, check mark button, accept, yes, success, task'],['✊','fist','justice, raised fist, solidarity, empowerment, fist, strength'],['✋','raised_hand','hand, stop, halt, raised hand'],['✨','sparkles','sparkles, stars, shine, AI, magic, beauty, creativity'],['❌','x','cross mark, cross, wrong, no, red'],['❎','negative_squared_cross_mark','cross, no, green,, cross mark button'],['❓','question','curiosity, question mark, question, punctuation, red'],['⭐','star','star, five, achievement, favorite, yellow, gold, space, universe'],['⭕','o','hoop, hollow red circle, o, circle, red, round'],['🀄','mahjong','mahjong red dragon, china, game'],['🃏','black_joker','card, joker, game, deck, gamble'],['🆎','ab','red,, AB button (blood type)'],['🆑','cl','CL button, red'],['🆒','cool','cool, blue, COOL button'],['🆓','free','free, blue, FREE button'],['🆔','id','authentication, security, purple, identification, id, verification, ID button'],['🆕','new','new, blue, NEW button'],['🆖','ng','blue, ana ng, NG button, ng'],['🆗','ok','blue, okay, ok, OK button'],['🆘','sos','SOS button, emergency, danger, red, help, sos'],['🆙','up','UP! button, up, blue'],['🆚','vs','versus, duel, orange, contest, challenge, vs, battle, competition, VS button'],['🈁','koko','here, blue, japanese, Japanese here button'],['🈚','u7121','Japanese free of charge button, orange, japanese'],['🈯','u6307','Japanese reserved button, japanese, green'],['🈲','u7981','Japanese prohibited button, red, japanese'],['🈳','u7a7a','blue, Japanese vacancy button, japanese'],['🈴','u5408','Japanese passing grade button, red, japanese'],['🈵','u6e80','Japanese no vacancy button, red, japanese'],['🈶','u6709','Japanese not free of charge button, orange, japanese'],['🈸','u7533','Japanese application button, orange, japanese'],['🈹','u5272','Japanese discount button, red, japanese'],['🈺','u55b6','Japanese open for business button, orange, japanese'],['🉐','ideograph_advantage','Japanese bargain button, red, japanese'],['🉑','accept','Japanese acceptable button, orange, japanese'],['🌀','cyclone','cyclone, spiral, Zen, purple, swirl, storm'],['🌁','foggy','foggy, bridge, cloudy'],['🌂','closed_umbrella',', umbrella, purple, rain, closed umbrella, weather'],['🌃','night_with_stars','night, city, night with stars, scenery'],['🌄','sunrise_over_mountains','sunrise, sunrise over mountains, sun, sunset, nature, scenery'],['🌅','sunrise','sun, sunset, sunrise, scenery, nature'],['🌆','city_dusk','cityscape at dusk, city,, scenery'],['🌇','city_sunset','city, evening, sunset, scenery'],['🌈','rainbow','rainbow, pride, gay'],['🌉','bridge_at_night','night, bridge, bridge at night'],['🌊','ocean','water wave, tsunami, water, blue, ocean, art, sea, wave'],['🌋','volcano','volcano, eruption, lava, fire, geological'],['🌌','milky_way','science, milky way, galaxy, cosmos, stars, blue, nebula'],['🌍','earth_africa','africa, blue, planet, school, map, world, earth, globe, globe showing Europe-Africa, geography'],['🌎','earth_americas','blue, planet, america, school, map, globe showing Americas, world, earth, globe, geography'],['🌏','earth_asia','globe showing Asia-Australia, blue, asia, planet, school, map, world, earth, globe, australia, geography'],['🌐','globe_with_meridians','globe with meridians, blue, tech, internet, www, world, network, technology, web'],['🌑','new_moon','moon, lunar, purple, night, new moon, space, astronomy'],['🌒','waxing_crescent_moon','night, waxing crescent moon, astronomy, space, moon'],['🌓','first_quarter_moon','night, first quarter moon, astronomy, space, moon'],['🌔','waxing_gibbous_moon','night, waxing gibbous moon, astronomy, space, moon'],['🌕','full_moon','night, astronomy, full moon, space, yellow, moon'],['🌖','waning_gibbous_moon','night, astronomy, waning gibbous moon, space, moon'],['🌗','last_quarter_moon','night, astronomy, last quarter moon, space, moon'],['🌘','waning_crescent_moon','night, astronomy, waning crescent moon, space, moon'],['🌙','crescent_moon','night, astronomy, crescent moon, space, moon'],['🌚','new_moon_with_face','night, face, new moon face, astronomy, purple, space, moon'],['🌛','first_quarter_moon_with_face','night, face, astronomy, first quarter moon face, smile, space, yellow, moon'],['🌜','last_quarter_moon_with_face','night, face, astronomy, smile, last quarter moon face, space, yellow, moon'],['🌝','full_moon_with_face','night, face, full moon face, astronomy, smile, space, yellow, moon'],['🌞','sun_with_face','sun with face, night, face, astronomy, smile, space, yellow, moon'],['🌟','star2','sparkle, night, star, glowing star, yellow'],['🌠','stars','night, falling, star, cosmos, shooting star'],['🌭','hotdog','hotdog, hot dog, food'],['🌮','taco','taco, food'],['🌯','burrito','food, wrap, shawarma, burrito'],['🌰','chestnut','food, chestnut, onion'],['🌱','seedling',', green, plant, growth, seedling'],['🌲','evergreen_tree','holidays, christmas, green, evergreen tree, spruce, tree'],['🌳','deciduous_tree','oak, deciduous tree, environment, plant, nature, forest, tree, green'],['🌴','palm_tree','palm tree, vacation, palm, island, tree, beach'],['🌵','cactus','cactus, desert, green, nature, plant'],['🌷','tulip','flower, tulip, pink, nature, plant'],['🌸','cherry_blossom','pink, bloom, plant, nature, flower, sakura, cherry blossom'],['🌹','rose','flower, rose, red, nature, plant'],['🌺','hibiscus','hibiscus, pink, plant, nature, flower'],['🌻','sunflower','sunflower, nature, plant, flower, yellow'],['🌼','blossom','blossom, plant, nature, flower, white'],['🌽','corn','food, corn, ear of corn'],['🌾','ear_of_rice','food, sheaf of rice, wheat'],['🌿','herb','herb, plant'],['🍀','four_leaf_clover','lucky, four leaf clover, fortune, clover, green, plant'],['🍁','maple_leaf','maple leaf, autumn, plant, nature, leaf, fall, red, canada'],['🍂','fallen_leaf','brown, leaf, autumn, plant, nature, fall, dead leaves, fallen leaf'],['🍃','leaves','nature, green, leaf, leaf fluttering in wind, plant'],['🍄','mushroom','mushroom, nature, plant, fungi, toadstool'],['🍅','tomato','tomato, food, vegetable, red'],['🍆','eggplant','eggplant, food, vegetable, purple'],['🍇','grapes','food, fruit, grapes, grape, purple'],['🍈','melon','melon, fruit, food'],['🍉','watermelon','watermelon, fruit, food, red'],['🍊','tangerine','food, fruit, tangerine, orange'],['🍋','lemon','lemon, food, fruit, yellow'],['🍌','banana','banana, food, fruit, berry, yellow'],['🍍','pineapple','pineapple, food, fruit'],['🍎','apple','food, red apple, fruit, apple, school,, red'],['🍏','green_apple','food, fruit, green, apple, green apple'],['🍐','pear','pear, food, fruit, green'],['🍑','peach','peach, food, fruit'],['🍒','cherries','food, fruit, cherries, cherry, red'],['🍓','strawberry','strawberry, berry, fruit, food, red'],['🍔','hamburger','hamburger, america, food'],['🍕','pizza','pizza, food'],['🍖','meat_on_bone','food, meat on bone, ham'],['🍗','poultry_leg','chicken, poultry leg, food'],['🍘','rice_cracker','rice cracker, rice'],['🍙','rice_ball','onigiri, rice, rice ball, food'],['🍚','rice','food, rice, cooked rice'],['🍛','curry','food, rice, curry, curry rice'],['🍜','ramen','food, steaming bowl, ramen, noodles'],['🍝','spaghetti','food, pasta, spaghetti'],['🍞','bread','bread, food'],['🍟','fries','fries, french fries, french, food'],['🍠','sweet_potato','food, roasted, roasted sweet potato, sweet, potato'],['🍡','dango','dango, food'],['🍢','oden','oden, food'],['🍣','sushi','sushi, salmon, food'],['🍤','fried_shrimp','food, prawn, fried shrimp'],['🍥','fish_cake',', fish cake with swirl'],['🍦','icecream','desert, icecrean, soft ice cream, food'],['🍧','shaved_ice','desert, icecrean, shaved ice, food'],['🍨','ice_cream','desert, ice cream, icecrean, food'],['🍩','doughnut','desert, donut, doughnut, food'],['🍪','cookie','cookie, desert, food'],['🍫','chocolate_bar','desert, chocolate, chocolate bar, food'],['🍬','candy','candy, desert, food'],['🍭','lollipop','desert, candy, lollipop, food'],['🍮','custard','custard, food, dessert'],['🍯','honey_pot','food, honey, honey pot'],['🍰','cake','food, shortcake, cakedesert'],['🍱','bento','bento, rice, bento box, food'],['🍲','stew','food, soup, pot of food'],['🍳','cooking','food, cooking, omelette, egg'],['🍴','fork_and_knife','cutlery, food, fork and knife, fork, knife'],['🍵','tea','chai, food, drink, tea, teacup without handle'],['🍶','sake','sake, drink'],['🍷','wine_glass','food, wine glass, wine, drink'],['🍸','cocktail','food, glass, cocktail glass, drink, cocktail, martini'],['🍹','tropical_drink','drink, tropical drink, long island, food'],['🍺','beer','food, beer mug, drink, beer'],['🍻','beers','food, clinking beer mugs, drink, beer'],['🍼','baby_bottle','food, baby bottle, drink, baby, milk'],['🍾','champagne','drink, bottle with popping cork, champagne, food'],['🍿','popcorn','popcorn, food'],['🎀','ribbon','decoration, present, bow, ribbon, cute'],['🎁','gift','wrapped gift, present, christmas'],['🎂','birthday','birthday, birthday cake, cake'],['🎃','jack_o_lantern','scary, pumpkin, spooky, fall, orange, halloween, jack-o-lantern'],['🎄','christmas_tree','Christmas tree, tree, christmas, holidays'],['🎅','santa','santa, Santa Claus, christmas, holidays'],['🎆','fireworks','fireworks, party'],['🎇','sparkler','fireworks, sparkler, party'],['🎈','balloon','baloon, red, balloon'],['🎉','tada','confetti, party, party popper, celebration'],['🎊','confetti_ball','confetti, party, confetti ball, celebration'],['🎋','tanabata_tree','tanabata, tree, tanabata tree'],['🎌','crossed_flags',', crossed flags'],['🎍','bamboo','bamboo, pine decoration'],['🎎','dolls',', Japanese dolls'],['🎏','flags',', carp streamer'],['🎐','wind_chime',', wind chime'],['🎑','rice_scene',', moon viewing ceremony'],['🎒','school_satchel','school, backpack, bag'],['🎓','mortar_board','graduation, graduate, education, school, graduation cap, university'],['🎠','carousel_horse','park, carousel, carousel horse, pony'],['🎡','ferris_wheel','park, ferris, ferris wheel, wheel'],['🎢','roller_coaster','park, roller coaster, rollercoaster'],['🎣','fishing_pole_and_fish','fishing, fishing pole, fish, rod'],['🎤','microphone','microphone, speech, talk, singing'],['🎥','movie_camera','recording, movie camera, cinema, film, video, camera, content creation'],['🎦','cinema','camera, blue, recording, video, film, cinema'],['🎧','headphones','music, headphone, headphones, audio'],['🎨','art','colors, artist palette, creativity, design, painting, art, inspiration'],['🎩','tophat','hat, top hat, magic'],['🎪','circus_tent','circus, circus tent'],['🎫','ticket','ticket'],['🎬','clapper','video editing, media, video, clapper board, audiovisual'],['🎭','performing_arts','theater, performing arts, drama, masks'],['🎮','video_game','xbox, ps4, gaming, video game, playstation'],['🎯','dart','direct hit, goal, target, task'],['🎰','slot_machine','slot, casino, slot machine, games, gambling'],['🎱','8ball','billiard, games, ball, 8, eight, pool 8 ball'],['🎲','game_die','dice, luck, games, one, 1, game die'],['🎳','bowling','bowling, games, games'],['🎴','flower_playing_cards','play, card, flower playing cards'],['🎵','musical_note','note, musical note, song, music'],['🎶','notes','note, song, music, musical notes'],['🎷','saxophone','instrument, song, music, sax, saxophone'],['🎸','guitar','music, guitar, instrument, electric, song'],['🎹','musical_keyboard','instrument, song, music, piano, musical keyboard'],['🎺','trumpet','music, trumpet, instrument, song'],['🎻','violin','music, instrument, violin, sound'],['🎼','musical_score','musical score, sound, music'],['🎽','running_shirt_with_sash','clothes, running shirt, vest'],['🎾','tennis','tennis, sport'],['🎿','ski','scating, sport, skis'],['🏀','basketball','basketball, sport, orange'],['🏁','checkered_flag','finish, sport, chequered flag, race'],['🏂','snowboarder','snowboarder, snowboard, sport, snow'],['🏃','person_running','person running, sport, running'],['🏄','person_surfing','person surfing, surfing, sport'],['🏅','medal','gold, win, medal, sports medal'],['🏆','trophy','trophy, win, gold'],['🏇','horse_racing','horse racing, horse, sport, racing'],['🏈','football','american football, brown, football, sport'],['🏉','rugby_football','rugby football, football, sport'],['🏊','person_swimming','sport, swimming, person swimming'],['🏏','cricket_game','baseball, sport, cricket, cricket game'],['🏐','volleyball','white, football, volleyball, sport'],['🏑','field_hockey','hockey, field hockey, sport, field'],['🏒','hockey','hockey, ice hockey, sport'],['🏓','ping_pong','ping pong, tennis, sport'],['🥋', 'martial_arts_uniform', 'martial arts uniform, martial arts, judo, bjj, jiu jitsu, kimono, gi, fighting, sport'],['🏠','house','home, house, building'],['🏡','house_with_garden','building, house with garden, home, house'],['🏢','office','office building, work, building, office'],['🏣','post_office','building, post, office, Japanese post office'],['🏤','european_post_office','post office, building, post, office'],['🏥','hospital','hospital, building, health'],['🏦','bank','bank, money, building'],['🏧','atm','atm, ATM sign, blue'],['🏨','hotel','hotel, building'],['🏩','love_hotel','love, building, hotel, love hotel'],['🏪','convenience_store','store, building, shop, groceries, convenience store, convenience'],['🏫','school','school, building'],['🏬','department_store','store, building, department store'],['🏭','factory','factory, work, building'],['🏮','izakaya_lantern','lamp, red paper lantern, light'],['🏯','japanese_castle','building, Japanese castle, temple, castle, fortress'],['🏰','european_castle','temple, castle, fortress, building'],['🏴','flag_black','black flag, flag, black'],['🏸','badminton','badminton, racket, sport'],['🏹','bow_and_arrow','archery, bow and arrow, sport'],['🏺','amphora','amphora, vase'],['🐀','rat','animal, rat'],['🐁','mouse2','animal, mouse'],['🐂','ox','animal, ox'],['🐃','water_buffalo',', water buffalo'],['🐄','cow2','animal, cow'],['🐅','tiger2','animal, tiger'],['🐆','leopard','animal, leopard'],['🐇','rabbit2','animal, rabbit, bunny, hair'],['🐈','cat2','animal, cat'],['🐉','dragon','animal, dragon'],['🐊','crocodile','alagator, animal, crocodile, green'],['🐋','whale2','animal, whale, blue'],['🐌','snail','animal, snail'],['🐍','snake','animal, snake'],['🐎','racehorse','animal, horse'],['🐏','ram','animal, ram'],['🐐','goat','animal, goat'],['🐑','sheep','animal, ewe'],['🐒','monkey','animal, monkey'],['🐓','rooster','animal, rooster'],['🐔','chicken','chicken, animal'],['🐕','dog2','animal, dog'],['🐖','pig2','animal, pig'],['🐗','boar','animal, boar'],['🐘','elephant','animal, elephant'],['🐙','octopus','animal, octopus'],['🐚','shell','spiral shell, seashell, sea, beach, ocean'],['🐛','bug','animal, insect, bug'],['🐜','ant','animal, insect, ant, bug'],['🐝','bee','animal, insect, bug, honeybee'],['🐞','beetle','animal, insect, bug, lady beetle'],['🐟','fish','animal, fish'],['🐠','tropical_fish','tropical fish, animal'],['🐡','blowfish','animal, blowfish'],['🐢','turtle','animal, turtle, green'],['🐣','hatching_chick','hatching chick, animal'],['🐤','baby_chick','animal, baby chick'],['🐥','hatched_chick','animal, front-facing baby chick'],['🐦','bird','animal, bird'],['🐧','penguin','linux, animal, penguin'],['🐨','koala','animal, koala'],['🐩','poodle','animal, poodle'],['🐪','dromedary_camel','animal, camel'],['🐫','camel','animal, two-hump camel'],['🐬','dolphin','animal, dolphin'],['🐭','mouse','animal, mouse face, face'],['🐮','cow','animal, face, cow face'],['🐯','tiger','tiger face, animal, face'],['🐰','rabbit','animal, cute, rabbit face'],['🐱','cat','animal, cat face, face, cute'],['🐲','dragon_face','animal, dragon face'],['🐳','whale','animal, spouting whale'],['🐴','horse','animal, face, horse face'],['🐵','monkey_face','monkey face, animal, face'],['🐶','dog','animal, face, dog face'],['🐷','pig','animal, face, pig face'],['🐸','frog','frog, animal, face'],['🐹','hamster','animal, face, hamster'],['🐺','wolf','animal, face, wolf'],['🐻','bear','animal, face, bear'],['🐼','panda_face','animal, panda'],['🐽','pig_nose','animal, pig nose, nose'],['🐾','feet','animal, tracks, paw prints'],['👀','eyes','looking, eyes'],['👂','ear','listen, sound, ear'],['👃','nose','nose, smell'],['👄','lips','mouth'],['👅','tongue','tongue, silly, mouth'],['👆','point_up_2',', backhand index pointing up'],['👇','point_down',', backhand index pointing down'],['👈','point_left',', backhand index pointing left'],['👉','point_right',', backhand index pointing right'],['👊','punch',', oncoming fist'],['👋','wave',', waving hand'],['👌','ok_hand',', OK hand'],['👍','thumbsup',', thumbs up'],['👎','thumbsdown',', thumbs down'],['👏','clap',', clapping hands'],['👐','open_hands',', open hands'],['👑','crown',', crown'],['👒','womans_hat',', woman’s hat'],['👓','eyeglasses',', glasses'],['👔','necktie',', necktie'],['👕','shirt',', t-shirt'],['👖','jeans',', jeans'],['👗','dress',', dress'],['👘','kimono',', kimono'],['👙','bikini',', bikini'],['👚','womans_clothes',', woman’s clothes'],['👛','purse',', purse'],['👜','handbag',', handbag'],['👝','pouch',', clutch bag'],['👞','mans_shoe',', man’s shoe'],['👟','athletic_shoe',', running shoe'],['👠','high_heel',', high-heeled shoe'],['👡','sandal',', woman’s sandal'],['👢','boot',', woman’s boot'],['👣','footprints',', footprints'],['👤','bust_in_silhouette',', bust in silhouette'],['👥','busts_in_silhouette',', busts in silhouette'],['👦','boy',', boy'],['👧','girl',', girl'],['👨','man',', man'],['👩','woman',', woman'],['👪','family',', family'],['👫','couple',', woman and man holding hands'],['👬','two_men_holding_hands',', men holding hands'],['👭','two_women_holding_hands',', women holding hands'],['👮','police_officer',', police officer'],['👯','people_with_bunny_ears_partying',', people with bunny ears'],['👰','bride_with_veil',', bride with veil'],['👱','blond_haired_person',', person: blond hair'],['👲','man_with_chinese_cap',', man with skullcap'],['👳','person_wearing_turban',', person wearing turban'],['👴','older_man',', old man'],['👵','older_woman',', old woman'],['👶','baby',', baby'],['👷','construction_worker',', construction worker'],['👸','princess',', princess'],['👹','japanese_ogre',', ogre'],['👺','japanese_goblin',', goblin'],['👻','ghost','ghost, halloween'],['👼','angel',', baby angel'],['👽','alien',', alien'],['👾','space_invader',', alien monster'],['👿','imp',', angry face with horns'],['💀','skull','spooky, skull, horror, bones'],['💁','person_tipping_hand','person tipping hand, questions'],['💂','guard',', guard'],['💃','dancer',', woman dancing'],['💄','lipstick','makeup, lipstick'],['💅','nail_care','beauty, nail polish, makeup'],['💆','person_getting_massage',', person getting massage'],['💇','person_getting_haircut',', person getting haircut'],['💈','barber',', barber pole'],['💉','syringe',', syringe'],['💊','pill',', pill'],['💋','kiss',', kiss mark'],['💌','love_letter',', love letter'],['💍','ring',', ring'],['💎','gem',', gem stone'],['💏','couplekiss',', kiss'],['💐','bouquet',', bouquet'],['💑','couple_with_heart',', couple with heart'],['💒','wedding',', wedding'],['💓','heartbeat',', beating heart'],['💔','broken_heart',', broken heart'],['💕','two_hearts',', two hearts'],['💖','sparkling_heart',', sparkling heart'],['💗','heartpulse',', growing heart'],['💘','cupid',', heart with arrow'],['💙','blue_heart',', blue heart'],['💚','green_heart',', green heart'],['💛','yellow_heart',', yellow heart'],['💜','purple_heart',', purple heart'],['💝','gift_heart',', heart with ribbon'],['💞','revolving_hearts',', revolving hearts'],['💟','heart_decoration',', heart decoration'],['💠','diamond_shape_with_a_dot_inside',', diamond with a dot'],['💡','bulb',', light bulb'],['💢','anger',', anger symbol'],['💣','bomb',', bomb'],['💤','zzz',', zzz'],['💥','boom',', collision'],['💦','sweat_drops',', sweat droplets'],['💧','droplet',', droplet'],['💨','dash',', dashing away'],['💩','poop',', pile of poo'],['💪','muscle',', flexed biceps'],['💫','dizzy',', dizzy'],['💬','speech_balloon',', speech balloon'],['💭','thought_balloon',', thought balloon'],['💮','white_flower',', white flower'],['💯','100',', hundred points'],['💰','moneybag',', money bag'],['💱','currency_exchange',', currency exchange'],['💲','heavy_dollar_sign',', heavy dollar sign'],['💳','credit_card',', credit card'],['💴','yen',', yen banknote'],['💵','dollar',', dollar banknote'],['💶','euro',', euro banknote'],['💷','pound',', pound banknote'],['💸','money_with_wings',', money with wings'],['💹','chart',', chart increasing with yen'],['💺','seat',', seat'],['💻','computer',', laptop'],['💼','briefcase',', briefcase'],['💽','minidisc',', computer disk'],['💾','floppy_disk',', floppy disk'],['💿','cd',', optical disk'],['📀','dvd',', dvd'],['📁','file_folder',', file folder'],['📂','open_file_folder',', open file folder'],['📃','page_with_curl',', page with curl'],['📄','page_facing_up',', page facing up'],['📅','date',', calendar'],['📆','calendar',', tear-off calendar'],['📇','card_index',', card index'],['📈','chart_with_upwards_trend',', chart increasing'],['📉','chart_with_downwards_trend',', chart decreasing'],['📊','bar_chart',', bar chart'],['📋','clipboard',', clipboard'],['📌','pushpin',', pushpin'],['📍','round_pushpin',', round pushpin'],['📎','paperclip',', paperclip'],['📏','straight_ruler',', straight ruler'],['📐','triangular_ruler',', triangular ruler'],['📑','bookmark_tabs',', bookmark tabs'],['📒','ledger',', ledger'],['📓','notebook',', notebook'],['📔','notebook_with_decorative_cover',', notebook with decorative cover'],['📕','closed_book',', closed book'],['📖','book',', open book'],['📗','green_book',', green book'],['📘','blue_book',', blue book'],['📙','orange_book',', orange book'],['📚','books','books, study, school'],['📛','name_badge',', name badge'],['📜','scroll',', scroll'],['📝','pencil','pencil, memo, note, school, study'],['📞','telephone_receiver','call, telephone receiver, phone'],['📟','pager',', pager'],['📠','fax',', fax machine'],['📡','satellite',', satellite antenna'],['📢','loudspeaker',', loudspeaker'],['📣','mega',', megaphone'],['📤','outbox_tray',', outbox tray'],['📥','inbox_tray',', inbox tray'],['📦','package',', package'],['📧','e-mail','mail, e-mail'],['📨','incoming_envelope','mail, incoming envelope'],['📩','envelope_with_arrow','mail, envelope with arrow'],['📪','mailbox_closed','closed mailbox with lowered flag, mail'],['📫','mailbox','mail, closed mailbox with raised flag'],['📬','mailbox_with_mail','mail, open mailbox with raised flag'],['📭','mailbox_with_no_mail','mail, open mailbox with lowered flag'],['📮','postbox',', postbox'],['📯','postal_horn',', postal horn'],['📰','newspaper',', newspaper'],['📱','iphone',', mobile phone'],['📲','calling',', mobile phone with arrow'],['📳','vibration_mode',', vibration mode'],['📴','mobile_phone_off',', mobile phone off'],['📵','no_mobile_phones',', no mobile phones'],['📶','signal_strength',', antenna bars'],['📷','camera','photo, photography, camera'],['📸','camera_with_flash','camera with flash, photo, photography'],['📹','video_camera',', video camera'],['📺','tv',', television'],['📻','radio',', radio'],['📼','vhs',', videocassette'],['📿','prayer_beads',', prayer beads'],['🔀','twisted_rightwards_arrows',', shuffle tracks button'],['🔁','repeat',', repeat button'],['🔂','repeat_one',', repeat single button'],['🔃','arrows_clockwise',', clockwise vertical arrows'],['🔄','arrows_counterclockwise',', counterclockwise arrows button'],['🔅','low_brightness',', dim button'],['🔆','high_brightness',', bright button'],['🔇','mute',', muted speaker'],['🔈','speaker',', speaker low volume'],['🔉','sound',', speaker medium volume'],['🔊','loud_sound',', speaker high volume'],['🔋','battery',', battery'],['🔌','electric_plug',', electric plug'],['🔍','mag','magnifying glass tilted left, search'],['🔎','mag_right','search, magnifying glass tilted right'],['🔏','lock_with_ink_pen',', locked with pen'],['🔐','closed_lock_with_key',', locked with key'],['🔑','key',', key'],['🔒','lock',', locked'],['🔓','unlock',', unlocked'],['🔔','bell',', bell'],['🔕','no_bell',', bell with slash'],['🔖','bookmark',', bookmark'],['🔗','link',', link'],['🔘','radio_button',', radio button'],['🔙','back',', BACK arrow'],['🔚','end',', END arrow'],['🔛','on',', ON! arrow'],['🔜','soon',', SOON arrow'],['🔝','top',', TOP arrow'],['🔞','underage',', no one under eighteen'],['🔟','keycap_ten',', keycap: 10'],['🔠','capital_abcd',', input latin uppercase'],['🔡','abcd',', input latin lowercase'],['🔢','1234',', input numbers'],['🔣','symbols',', input symbols'],['🔤','abc',', input latin letters'],['🔥','fire',', fire'],['🔦','flashlight',', flashlight'],['🔧','wrench',', wrench'],['🔨','hammer',', hammer'],['🔩','nut_and_bolt',', nut and bolt'],['🔪','knife',', kitchen knife'],['🔫','gun',', pistol'],['🔬','microscope',', microscope'],['🔭','telescope',', telescope'],['🔮','crystal_ball',', crystal ball'],['🔯','six_pointed_star',', dotted six-pointed star'],['🔰','beginner',', Japanese symbol for beginner'],['🔱','trident',', trident emblem'],['🔲','black_square_button',', black square button'],['🔳','white_square_button',', white square button'],['🔴','red_circle',', red circle'],['🔵','blue_circle',', blue circle'],['🔶','large_orange_diamond',', large orange diamond'],['🔷','large_blue_diamond',', large blue diamond'],['🔸','small_orange_diamond',', small orange diamond'],['🔹','small_blue_diamond',', small blue diamond'],['🔺','small_red_triangle',', red triangle pointed up'],['🔻','small_red_triangle_down',', red triangle pointed down'],['🔼','arrow_up_small',', upwards button'],['🔽','arrow_down_small',', downwards button'],['🕋','kaaba',', kaaba'],['🕌','mosque',', mosque'],['🕍','synagogue',', synagogue'],['🕎','menorah',', menorah'],['🕐','clock1',', one o’clock'],['🕑','clock2',', two o’clock'],['🕒','clock3',', three o’clock'],['🕓','clock4',', four o’clock'],['🕔','clock5',', five o’clock'],['🕕','clock6',', six o’clock'],['🕖','clock7',', seven o’clock'],['🕗','clock8',', eight o’clock'],['🕘','clock9',', nine o’clock'],['🕙','clock10',', ten o’clock'],['🕚','clock11',', eleven o’clock'],['🕛','clock12',', twelve o’clock'],['🕜','clock130',', one-thirty'],['🕝','clock230',', two-thirty'],['🕞','clock330',', three-thirty'],['🕟','clock430',', four-thirty'],['🕠','clock530',', five-thirty'],['🕡','clock630',', six-thirty'],['🕢','clock730',', seven-thirty'],['🕣','clock830',', eight-thirty'],['🕤','clock930',', nine-thirty'],['🕥','clock1030',', ten-thirty'],['🕦','clock1130',', eleven-thirty'],['🕧','clock1230',', twelve-thirty'],['🖕','middle_finger',', middle finger'],['🖖','vulcan',', vulcan salute'],['🗻','mount_fuji',', mount fuji'],['🗼','tokyo_tower',', Tokyo tower'],['🗽','statue_of_liberty',', Statue of Liberty'],['🗾','japan',', map of Japan'],['🗿','moyai',', moai'],['😀','grinning',', grinning face'],['😁','grin',', beaming face with smiling eyes'],['😂','joy',', face with tears of joy'],['😃','smiley',', grinning face with big eyes'],['😄','smile',', grinning face with smiling eyes'],['😅','sweat_smile',', grinning face with sweat'],['😆','laughing',', grinning squinting face'],['😇','innocent',', smiling face with halo'],['😈','smiling_imp',', smiling face with horns'],['😉','wink',', winking face'],['😊','blush',', smiling face with smiling eyes'],['😋','yum',', face savoring food'],['😌','relieved',', relieved face'],['😍','heart_eyes',', smiling face with heart-eyes'],['😎','sunglasses',', smiling face with sunglasses'],['😏','smirk',', smirking face'],['😐','neutral_face',', neutral face'],['😑','expressionless',', expressionless face'],['😒','unamused',', unamused face'],['😓','sweat',', downcast face with sweat'],['😔','pensive',', pensive face'],['😕','confused',', confused face'],['😖','confounded',', confounded face'],['😗','kissing',', kissing face'],['😘','kissing_heart',', face blowing a kiss'],['😙','kissing_smiling_eyes',', kissing face with smiling eyes'],['😚','kissing_closed_eyes',', kissing face with closed eyes'],['😛','stuck_out_tongue',', face with tongue'],['😜','stuck_out_tongue_winking_eye',', winking face with tongue'],['😝','stuck_out_tongue_closed_eyes',', squinting face with tongue'],['😞','disappointed',', disappointed face'],['😟','worried',', worried face'],['😠','angry',', angry face'],['😡','rage',', pouting face'],['😢','cry',', crying face'],['😣','persevere',', persevering face'],['😤','triumph',', face with steam from nose'],['😥','disappointed_relieved',', sad but relieved face'],['😦','frowning',', frowning face with open mouth'],['😧','anguished',', anguished face'],['😨','fearful',', fearful face'],['😩','weary',', weary face'],['😪','sleepy',', sleepy face'],['😫','tired_face',', tired face'],['😬','grimacing',', grimacing face'],['😭','sob',', loudly crying face'],['😮','open_mouth',', face with open mouth'],['😯','hushed',', hushed face'],['😰','cold_sweat',', anxious face with sweat'],['😱','scream',', face screaming in fear'],['😲','astonished',', astonished face'],['😳','flushed',', flushed face'],['😴','sleeping',', sleeping face'],['😵','dizzy_face',', dizzy face'],['😶','no_mouth',', face without mouth'],['😷','mask',', face with medical mask'],['😸','smile_cat',', grinning cat with smiling eyes'],['😹','joy_cat',', cat with tears of joy'],['😺','smiley_cat','grinning cat, kitty'],['😻','heart_eyes_cat',', smiling cat with heart-eyes'],['😼','smirk_cat',', cat with wry smile'],['😽','kissing_cat',', kissing cat'],['😾','pouting_cat',', pouting cat'],['😿','crying_cat_face',', crying cat'],['🙀','scream_cat',', weary cat'],['🙁','slight_frown',', slightly frowning face'],['🙂','slight_smile',', slightly smiling face'],['🙃','upside_down',', upside-down face'],['🙄','rolling_eyes',', face with rolling eyes'],['🙅','person_gesturing_no',', person gesturing NO'],['🙆','person_gesturing_ok',', person gesturing OK'],['🙇','person_bowing',', person bowing'],['🙈','see_no_evil',', see-no-evil monkey'],['🙉','hear_no_evil',', hear-no-evil monkey'],['🙊','speak_no_evil',', speak-no-evil monkey'],['🙋','person_raising_hand',', person raising hand'],['🙌','raised_hands',', raising hands'],['🙍','person_frowning',', person frowning'],['🙎','person_pouting',', person pouting'],['🙏','pray',', folded hands'],['🚀','rocket',', rocket'],['🚁','helicopter',', helicopter'],['🚂','steam_locomotive',', locomotive'],['🚃','railway_car',', railway car'],['🚄','bullettrain_side',', high-speed train'],['🚅','bullettrain_front',', bullet train'],['🚆','train2',', train'],['🚇','metro',', metro'],['🚈','light_rail',', light rail'],['🚉','station',', station'],['🚊','tram',', tram'],['🚋','train',', tram car'],['🚌','bus',', bus'],['🚍','oncoming_bus',', oncoming bus'],['🚎','trolleybus',', trolleybus'],['🚏','busstop',', bus stop'],['🚐','minibus',', minibus'],['🚑','ambulance',', ambulance'],['🚒','fire_engine',', fire engine'],['🚓','police_car',', police car'],['🚔','oncoming_police_car',', oncoming police car'],['🚕','taxi',', taxi'],['🚖','oncoming_taxi',', oncoming taxi'],['🚗','red_car',', automobile'],['🚘','oncoming_automobile',', oncoming automobile'],['🚙','blue_car',', sport utility vehicle'],['🚚','truck',', delivery truck'],['🚛','articulated_lorry',', articulated lorry'],['🚜','tractor',', tractor'],['🚝','monorail',', monorail'],['🚞','mountain_railway',', mountain railway'],['🚟','suspension_railway',', suspension railway'],['🚠','mountain_cableway',', mountain cableway'],['🚡','aerial_tramway',', aerial tramway'],['🚢','ship',', ship'],['🚣','person_rowing_boat',', person rowing boat'],['🚤','speedboat',', speedboat'],['🚥','traffic_light',', horizontal traffic light'],['🚦','vertical_traffic_light',', vertical traffic light'],['🚧','construction',', construction'],['🚨','rotating_light',', police car light'],['🚩','triangular_flag_on_post',', triangular flag'],['🚪','door',', door'],['🚫','no_entry_sign',', prohibited'],['🚬','smoking',', cigarette'],['🚭','no_smoking',', no smoking'],['🚮','put_litter_in_its_place',', litter in bin sign'],['🚯','do_not_litter',', no littering'],['🚰','potable_water',', potable water'],['🚱','non-potable_water',', non-potable water'],['🚲','bike',', bicycle'],['🚳','no_bicycles',', no bicycles'],['🚴','person_biking',', person biking'],['🚵','person_mountain_biking',', person mountain biking'],['🚶','person_walking',', person walking'],['🚷','no_pedestrians',', no pedestrians'],['🚸','children_crossing',', children crossing'],['🚹','mens',', men’s room'],['🚺','womens',', women’s room'],['🚻','restroom',', restroom'],['🚼','baby_symbol',', baby symbol'],['🚽','toilet',', toilet'],['🚾','wc',', water closet'],['🚿','shower',', shower'],['🛀','bath',', person taking bath'],['🛁','bathtub',', bathtub'],['🛂','passport_control',', passport control'],['🛃','customs',', customs'],['🛄','baggage_claim',', baggage claim'],['🛅','left_luggage',', left luggage'],['🛌','sleeping_accommodation',', person in bed'],['🛐','place_of_worship',', place of worship'],['🛫','airplane_departure',', airplane departure'],['🛬','airplane_arriving',', airplane arrival'],['🤐','zipper_mouth',', zipper-mouth face'],['🤑','money_mouth',', money-mouth face'],['🤒','thermometer_face',', face with thermometer'],['🤓','nerd',', nerd face'],['🤔','thinking',', thinking face'],['🤕','head_bandage',', face with head-bandage'],['🤖','robot','robot, electronics, AI, artificial intelligence, tech, technology'],['🤗','hugging','hugging face, AI, artificial intelligence'],['🤘','metal','hand, rock, sign of the horns'],['🦀','crab','sea creature, crab, animal, sea, seafood'],['🦁','lion_face','animal, lion'],['🦂','scorpion','animal, scorpion'],['🦃','turkey','turkey, bird,, thanksgiving'],['🦄','unicorn','magic, fantasy, rainbow, unicorn'],['🧀','cheese','food, mouse, cheese wedge'],['🇦🇨','flag_ac','flags, flag: Ascension Island, flag'],['🇦🇩','flag_ad','flag: Andorra, flags, flag'],['🇦🇪','flag_ae','flags, flag: United Arab Emirates, flag'],['🇦🇫','flag_af','flags, flag, flag: Afghanistan'],['🇦🇬','flag_ag','flag: Antigua & Barbuda, flags, flag'],['🇦🇮','flag_ai','flags, flag, flag: Anguilla'],['🇦🇱','flag_al','flag: Albania, flags, flag'],['🇦🇲','flag_am','flags, flag: Armenia, flag'],['🇦🇴','flag_ao','flags, flag, flag: Angola'],['🇦🇶','flag_aq','flag: Antarctica, flags, flag'],['🇦🇷','flag_ar','flags, flag: Argentina, flag'],['🇦🇸','flag_as','flags, flag: American Samoa, flag'],['🇦🇹','flag_at','flags, flag, flag: Austria'],['🇦🇺','flag_au','flags, flag, flag: Australia'],['🇦🇼','flag_aw','flag: Aruba, flags, flag'],['🇦🇽','flag_ax','flag: Åland Islands, flags, flag'],['🇦🇿','flag_az','flags, flag, flag: Azerbaijan'],['🇧🇦','flag_ba','flag: Bosnia & Herzegovina, flags, flag'],['🇧🇧','flag_bb','flag: Barbados, flags, flag'],['🇧🇩','flag_bd','flags, flag, flag: Bangladesh'],['🇧🇪','flag_be','flags, flag, flag: Belgium'],['🇧🇫','flag_bf','flags, flag: Burkina Faso, flag'],['🇧🇬','flag_bg','flag: Bulgaria, flags, flag'],['🇧🇭','flag_bh','flags, flag: Bahrain, flag'],['🇧🇮','flag_bi','flag: Burundi, flags, flag'],['🇧🇯','flag_bj','flag: Benin, flags, flag'],['🇧🇱','flag_bl','flags, flag: St. Barthélemy, flag'],['🇧🇲','flag_bm','flags, flag: Bermuda, flag'],['🇧🇳','flag_bn','flags, flag: Brunei, flag'],['🇧🇴','flag_bo','flag: Bolivia, flags, flag'],['🇧🇶','flag_bq','flags, flag: Caribbean Netherlands, flag'],['🇧🇷','flag_br','flag: Brazil, flags, flag'],['🇧🇸','flag_bs','flag: Bahamas, flags, flag'],['🇧🇹','flag_bt','flags, flag: Bhutan, flag'],['🇧🇻','flag_bv','flag: Bouvet Island, flags, flag'],['🇧🇼','flag_bw','flags, flag, flag: Botswana'],['🇧🇾','flag_by','flags, flag, flag: Belarus'],['🇧🇿','flag_bz','flag: Belize, flags, flag'],['🇨🇦','flag_ca','flag: Canada, flags, flag'],['🇨🇨','flag_cc','flags, flag: Cocos (Keeling) Islands, flag'],['🇨🇩','flag_cd','flag: Congo - Kinshasa, flags, flag'],['🇨🇫','flag_cf','flag: Central African Republic, flags, flag'],['🇨🇬','flag_cg','flags, flag: Congo - Brazzaville, flag'],['🇨🇭','flag_ch','flags, flag: Switzerland, flag'],['🇨🇮','flag_ci','flags, flag: Côte d’Ivoire, flag'],['🇨🇰','flag_ck','flag: Cook Islands, flags, flag'],['🇨🇱','flag_cl','flag: Chile, flags, flag'],['🇨🇲','flag_cm','flag: Cameroon, flags, flag'],['🇨🇳','flag_cn','flags, flag, flag: China'],['🇨🇴','flag_co','flags, flag: Colombia, flag'],['🇨🇵','flag_cp','flags, flag, flag: Clipperton Island'],['🇨🇷','flag_cr','flag: Costa Rica, flags, flag'],['🇨🇺','flag_cu','flag: Cuba, flags, flag'],['🇨🇻','flag_cv','flags, flag: Cape Verde, flag'],['🇨🇼','flag_cw','flag: Curaçao, flags, flag'],['🇨🇽','flag_cx','flags, flag: Christmas Island, flag'],['🇨🇾','flag_cy','flags, flag: Cyprus, flag'],['🇨🇿','flag_cz','flags, flag, flag: Czechia'],['🇩🇪','flag_de','flags, flag, flag: Germany'],['🇩🇬','flag_dg','flag: Diego Garcia, flags, flag'],['🇩🇯','flag_dj','flag: Djibouti, flags, flag'],['🇩🇰','flag_dk','flags, flag, flag: Denmark'],['🇩🇲','flag_dm','flags, flag: Dominica, flag'],['🇩🇴','flag_do','flags, flag: Dominican Republic, flag'],['🇩🇿','flag_dz','flag: Algeria, flags, flag'],['🇪🇦','flag_ea','flags, flag: Ceuta & Melilla, flag'],['🇪🇨','flag_ec','flag: Ecuador, flags, flag'],['🇪🇪','flag_ee','flags, flag, flag: Estonia'],['🇪🇬','flag_eg','flag: Egypt, flags, flag'],['🇪🇭','flag_eh','flags, flag: Western Sahara, flag'],['🇪🇷','flag_er','flags, flag, flag: Eritrea'],['🇪🇸','flag_es','flags, flag: Spain, flag'],['🇪🇹','flag_et','flags, flag: Ethiopia, flag'],['🇪🇺','flag_eu','flags, flag: European Union, flag'],['🇫🇮','flag_fi','flag: Finland, flags, flag'],['🇫🇯','flag_fj','flags, flag, flag: Fiji'],['🇫🇰','flag_fk','flags, flag: Falkland Islands, flag'],['🇫🇲','flag_fm','flags, flag: Micronesia, flag'],['🇫🇴','flag_fo','flags, flag: Faroe Islands, flag'],['🇫🇷','flag_fr','flag: France, flags, flag'],['🇬🇦','flag_ga','flags, flag: Gabon, flag'],['🇬🇧','flag_gb','flag: United Kingdom, flags, flag'],['🇬🇩','flag_gd','flag: Grenada, flags, flag'],['🇬🇪','flag_ge','flags, flag, flag: Georgia'],['🇬🇫','flag_gf','flags, flag, flag: French Guiana'],['🇬🇬','flag_gg','flag: Guernsey, flags, flag'],['🇬🇭','flag_gh','flag: Ghana, flags, flag'],['🇬🇮','flag_gi','flags, flag, flag: Gibraltar'],['🇬🇱','flag_gl','flags, flag: Greenland, flag'],['🇬🇲','flag_gm','flag: Gambia, flags, flag'],['🇬🇳','flag_gn','flags, flag: Guinea, flag'],['🇬🇵','flag_gp','flags, flag: Guadeloupe, flag'],['🇬🇶','flag_gq','flags, flag, flag: Equatorial Guinea'],['🇬🇷','flag_gr','flag: Greece, flags, flag'],['🇬🇸','flag_gs','flag: South Georgia & South Sandwich Islands, flags, flag'],['🇬🇹','flag_gt','flags, flag: Guatemala, flag'],['🇬🇺','flag_gu','flag: Guam, flags, flag'],['🇬🇼','flag_gw','flag: Guinea-Bissau, flags, flag'],['🇬🇾','flag_gy','flag: Guyana, flags, flag'],['🇭🇰','flag_hk','flag: Hong Kong SAR China, flags, flag'],['🇭🇲','flag_hm','flags, flag, flag: Heard & McDonald Islands'],['🇭🇳','flag_hn','flags, flag, flag: Honduras'],['🇭🇷','flag_hr','flags, flag: Croatia, flag'],['🇭🇹','flag_ht','flags, flag: Haiti, flag'],['🇭🇺','flag_hu','flags, flag: Hungary, flag'],['🇮🇨','flag_ic','flags, flag, flag: Canary Islands'],['🇮🇩','flag_id','flags, flag: Indonesia, flag'],['🇮🇪','flag_ie','flags, flag: Ireland, flag'],['🇮🇱','flag_il','flags, flag: Israel, flag'],['🇮🇲','flag_im','flag: Isle of Man, flags, flag'],['🇮🇳','flag_in','flags, flag, flag: India'],['🇮🇴','flag_io','flags, flag: British Indian Ocean Territory, flag'],['🇮🇶','flag_iq','flag: Iraq, flags, flag'],['🇮🇷','flag_ir','flags, flag, flag: Iran'],['🇮🇸','flag_is','flags, flag: Iceland, flag'],['🇮🇹','flag_it','flags, flag: Italy, flag'],['🇯🇪','flag_je','flags, flag, flag: Jersey'],['🇯🇲','flag_jm','flags, flag, flag: Jamaica'],['🇯🇴','flag_jo','flag: Jordan, flags, flag'],['🇯🇵','flag_jp','flags, flag: Japan, flag'],['🇰🇪','flag_ke','flag: Kenya, flags, flag'],['🇰🇬','flag_kg','flag: Kyrgyzstan, flags, flag'],['🇰🇭','flag_kh','flag: Cambodia, flags, flag'],['🇰🇮','flag_ki','flag: Kiribati, flags, flag'],['🇰🇲','flag_km','flags, flag, flag: Comoros'],['🇰🇳','flag_kn','flags, flag: St. Kitts & Nevis, flag'],['🇰🇵','flag_kp','flag: North Korea, flags, flag'],['🇰🇷','flag_kr','flags, flag: South Korea, flag'],['🇰🇼','flag_kw','flags, flag, flag: Kuwait'],['🇰🇾','flag_ky','flags, flag: Cayman Islands, flag'],['🇰🇿','flag_kz','flags, flag: Kazakhstan, flag'],['🇱🇦','flag_la','flags, flag, flag: Laos'],['🇱🇧','flag_lb','flags, flag, flag: Lebanon'],['🇱🇨','flag_lc','flag: St. Lucia, flags, flag'],['🇱🇮','flag_li','flags, flag, flag: Liechtenstein'],['🇱🇰','flag_lk','flags, flag, flag: Sri Lanka'],['🇱🇷','flag_lr','flag: Liberia, flags, flag'],['🇱🇸','flag_ls','flag: Lesotho, flags, flag'],['🇱🇹','flag_lt','flags, flag: Lithuania, flag'],['🇱🇺','flag_lu','flags, flag, flag: Luxembourg'],['🇱🇻','flag_lv','flag: Latvia, flags, flag'],['🇱🇾','flag_ly','flags, flag: Libya, flag'],['🇲🇦','flag_ma','flags, flag, flag: Morocco'],['🇲🇨','flag_mc','flags, flag, flag: Monaco'],['🇲🇩','flag_md','flag: Moldova, flags, flag'],['🇲🇪','flag_me','flag: Montenegro, flags, flag'],['🇲🇫','flag_mf','flags, flag, flag: St. Martin'],['🇲🇬','flag_mg','flags, flag, flag: Madagascar'],['🇲🇭','flag_mh','flags, flag: Marshall Islands, flag'],['🇲🇰','flag_mk','flags, flag, flag: North Macedonia'],['🇲🇱','flag_ml','flag: Mali, flags, flag'],['🇲🇲','flag_mm','flags, flag: Myanmar (Burma), flag'],['🇲🇳','flag_mn','flag: Mongolia, flags, flag'],['🇲🇴','flag_mo','flags, flag: Macao SAR China, flag'],['🇲🇵','flag_mp','flags, flag: Northern Mariana Islands, flag'],['🇲🇶','flag_mq','flags, flag: Martinique, flag'],['🇲🇷','flag_mr','flag: Mauritania, flags, flag'],['🇲🇸','flag_ms','flags, flag, flag: Montserrat'],['🇲🇹','flag_mt','flags, flag: Malta, flag'],['🇲🇺','flag_mu','flags, flag, flag: Mauritius'],['🇲🇻','flag_mv','flag: Maldives, flags, flag'],['🇲🇼','flag_mw','flags, flag: Malawi, flag'],['🇲🇽','flag_mx','flag: Mexico, flags, flag'],['🇲🇾','flag_my','flags, flag: Malaysia, flag'],['🇲🇿','flag_mz','flags, flag: Mozambique, flag'],['🇳🇦','flag_na','flags, flag, flag: Namibia'],['🇳🇨','flag_nc','flags, flag, flag: New Caledonia'],['🇳🇪','flag_ne','flags, flag: Niger, flag'],['🇳🇫','flag_nf','flags, flag, flag: Norfolk Island'],['🇳🇬','flag_ng','flags, flag: Nigeria, flag'],['🇳🇮','flag_ni','flags, flag: Nicaragua, flag'],['🇳🇱','flag_nl','flags, flag, flag: Netherlands'],['🇳🇴','flag_no','flag: Norway, flags, flag'],['🇳🇵','flag_np','flags, flag, flag: Nepal'],['🇳🇷','flag_nr','flags, flag: Nauru, flag'],['🇳🇺','flag_nu','flag: Niue, flags, flag'],['🇳🇿','flag_nz','flag: New Zealand, flags, flag'],['🇴🇲','flag_om','flags, flag: Oman, flag'],['🇵🇦','flag_pa','flags, flag, flag: Panama'],['🇵🇪','flag_pe','flag: Peru, flags, flag'],['🇵🇫','flag_pf','flag: French Polynesia, flags, flag'],['🇵🇬','flag_pg','flags, flag: Papua New Guinea, flag'],['🇵🇭','flag_ph','flags, flag, flag: Philippines'],['🇵🇰','flag_pk','flag: Pakistan, flags, flag'],['🇵🇱','flag_pl','flags, flag: Poland, flag'],['🇵🇲','flag_pm','flags, flag, flag: St. Pierre & Miquelon'],['🇵🇳','flag_pn','flags, flag, flag: Pitcairn Islands'],['🇵🇷','flag_pr','flag: Puerto Rico, flags, flag'],['🇵🇸','flag_ps','flags, flag: Palestinian Territories, flag'],['🇵🇹','flag_pt','flag: Portugal, flags, flag'],['🇵🇼','flag_pw','flag: Palau, flags, flag'],['🇵🇾','flag_py','flag: Paraguay, flags, flag'],['🇶🇦','flag_qa','flag: Qatar, flags, flag'],['🇷🇪','flag_re','flags, flag, flag: Réunion'],['🇷🇴','flag_ro','flags, flag, flag: Romania'],['🇷🇸','flag_rs','flags, flag: Serbia, flag'],['🇷🇺','flag_ru','flags, flag, flag: Russia'],['🇷🇼','flag_rw','flags, flag, flag: Rwanda'],['🇸🇦','flag_sa','flags, flag, flag: Saudi Arabia'],['🇸🇧','flag_sb','flag: Solomon Islands, flags, flag'],['🇸🇨','flag_sc','flags, flag: Seychelles, flag'],['🇸🇩','flag_sd','flags, flag, flag: Sudan'],['🇸🇪','flag_se','flag: Sweden, flags, flag'],['🇸🇬','flag_sg','flags, flag, flag: Singapore'],['🇸🇭','flag_sh','flags, flag, flag: St. Helena'],['🇸🇮','flag_si','flags, flag: Slovenia, flag'],['🇸🇯','flag_sj','flag: Svalbard & Jan Mayen, flags, flag'],['🇸🇰','flag_sk','flags, flag, flag: Slovakia'],['🇸🇱','flag_sl','flag: Sierra Leone, flags, flag'],['🇸🇲','flag_sm','flags, flag: San Marino, flag'],['🇸🇳','flag_sn','flags, flag: Senegal, flag'],['🇸🇴','flag_so','flags, flag, flag: Somalia'],['🇸🇷','flag_sr','flag: Suriname, flags, flag'],['🇸🇸','flag_ss','flags, flag: South Sudan, flag'],['🇸🇹','flag_st','flags, flag: São Tomé & Príncipe, flag'],['🇸🇻','flag_sv','flags, flag: El Salvador, flag'],['🇸🇽','flag_sx','flags, flag, flag: Sint Maarten'],['🇸🇾','flag_sy','flags, flag: Syria, flag'],['🇸🇿','flag_sz','flags, flag: Eswatini, flag'],['🇹🇦','flag_ta','flags, flag: Tristan da Cunha, flag'],['🇹🇨','flag_tc','flags, flag, flag: Turks & Caicos Islands'],['🇹🇩','flag_td','flags, flag: Chad, flag'],['🇹🇫','flag_tf','flag: French Southern Territories, flags, flag'],['🇹🇬','flag_tg','flags, flag, flag: Togo'],['🇹🇭','flag_th','flag: Thailand, flags, flag'],['🇹🇯','flag_tj','flag: Tajikistan, flags, flag'],['🇹🇰','flag_tk','flags, flag: Tokelau, flag'],['🇹🇱','flag_tl','flags, flag: Timor-Leste, flag'],['🇹🇲','flag_tm','flags, flag, flag: Turkmenistan'],['🇹🇳','flag_tn','flag: Tunisia, flags, flag'],['🇹🇴','flag_to','flags, flag, flag: Tonga'],['🇹🇷','flag_tr','flags, flag: Turkey, flag'],['🇹🇹','flag_tt','flags, flag, flag: Trinidad & Tobago'],['🇹🇻','flag_tv','flag: Tuvalu, flags, flag'],['🇹🇼','flag_tw','flag: Taiwan, flags, flag'],['🇹🇿','flag_tz','flag: Tanzania, flags, flag'],['🇺🇦','flag_ua','flags, flag, flag: Ukraine'],['🇺🇬','flag_ug','flags, flag: Uganda, flag'],['🇺🇲','flag_um','flags, flag, flag: U.S. Outlying Islands'],['🇺🇸','flag_us','flags, flag, flag: United States'],['🇺🇾','flag_uy','flags, flag, flag: Uruguay'],['🇺🇿','flag_uz','flags, flag, flag: Uzbekistan'],['🇻🇦','flag_va','flags, flag: Vatican City, flag'],['🇻🇨','flag_vc','flag: St. Vincent & Grenadines, flags, flag'],['🇻🇪','flag_ve','flags, flag, flag: Venezuela'],['🇻🇬','flag_vg','flag: British Virgin Islands, flags, flag'],['🇻🇮','flag_vi','flag: U.S. Virgin Islands, flags, flag'],['🇻🇳','flag_vn','flags, flag: Vietnam, flag'],['🇻🇺','flag_vu','flags, flag: Vanuatu, flag'],['🇼🇫','flag_wf','flag: Wallis & Futuna, flags, flag'],['🇼🇸','flag_ws','flag: Samoa, flags, flag'],['🇽🇰','flag_xk','flags, flag, flag: Kosovo'],['🇾🇪','flag_ye','flags, flag, flag: Yemen'],['🇾🇹','flag_yt','flags, flag, flag: Mayotte'],['🇿🇦','flag_za','flags, flag: South Africa, flag'],['🇿🇲','flag_zm','flags, flag: Zambia, flag'],['🇿🇼','flag_zw','flags, flag: Zimbabwe, flag'],['🏳️‍🌈','rainbow_flag','flag, rainbow flag, pride, gay, flags'],['🏳️‍⚧️','transgender_flag','trans, pride, flag, flags']];} \ No newline at end of file +function zenGlobalEmojis() { return [['⌚','watch','watch, clock, time, wristwatch'],['⌛','hourglass','hourglass done, time, sand, clock'],['⏪','rewind','arrow, blue, rewind, fast reverse button, left, back'],['⏫','arrow_double_up','increase, arrow, fast up button, blue, up'],['⏬','arrow_double_down','decrease, down, arrow, blue, fast down button'],['⏰','alarm_clock','alarm clock, clock, alarm, time, red'],['⏳','hourglass_flowing_sand','hourglass not done, time, sand, clock'],['⚽','soccer','sports, football, soccer ball, ball, soccer, soccer ball,'],['⚾','baseball','ball, baseball, sports'],['⛄','snowman','snowman, snowman without snow, christmas, holidays, snow'],['⛅','partly_sunny','sun, sun behind cloud, cloudy, sunny, weather'],['⛎','ophiuchus','zodiac, horoscope, Ophiuchus, purple'],['⛔','no_entry','sign, red, stop, no entry'],['⛪','church','church, building, religion, worship, faith, holy'],['⛲','fountain','fountain, water, garden'],['⛳','golf','sports, golf, flag in hole, flag'],['⛵','sailboat','vessel, vacation, sailing, sea, ship, sailboat, water, boat, travel, ocean'],['⛺','tent','camp, camping, outdoor, tent, camping, shelter, nature, vacation'],['⛽','fuelpump','oil, petrol, fuel pump, gas, red, gas station, fuel'],['✅','white_check_mark','approve, check, check mark, tick, check mark button, accept, yes, success, task'],['✊','fist','justice, raised fist, solidarity, empowerment, fist, strength'],['✋','raised_hand','hand, stop, halt, raised hand'],['✨','sparkles','sparkles, stars, shine, AI, magic, beauty, creativity'],['❌','x','cross mark, cross, wrong, no, red'],['❎','negative_squared_cross_mark','cross, no, green,, cross mark button'],['❓','question','curiosity, question mark, question, punctuation, red'],['⭐','star','star, five, achievement, favorite, yellow, gold, space, universe'],['⭕','o','hoop, hollow red circle, o, circle, red, round'],['🀄','mahjong','mahjong red dragon, china, game'],['🃏','black_joker','card, joker, game, deck, gamble'],['🆎','ab','red,, AB button (blood type)'],['🆑','cl','CL button, red'],['🆒','cool','cool, blue, COOL button'],['🆓','free','free, blue, FREE button'],['🆔','id','authentication, security, purple, identification, id, verification, ID button'],['🆕','new','new, blue, NEW button'],['🆖','ng','blue, ana ng, NG button, ng'],['🆗','ok','blue, okay, ok, OK button'],['🆘','sos','SOS button, emergency, danger, red, help, sos'],['🆙','up','UP! button, up, blue'],['🆚','vs','versus, duel, orange, contest, challenge, vs, battle, competition, VS button'],['🈁','koko','here, blue, japanese, Japanese here button'],['🈚','u7121','Japanese free of charge button, orange, japanese'],['🈯','u6307','Japanese reserved button, japanese, green'],['🈲','u7981','Japanese prohibited button, red, japanese'],['🈳','u7a7a','blue, Japanese vacancy button, japanese'],['🈴','u5408','Japanese passing grade button, red, japanese'],['🈵','u6e80','Japanese no vacancy button, red, japanese'],['🈶','u6709','Japanese not free of charge button, orange, japanese'],['🈸','u7533','Japanese application button, orange, japanese'],['🈹','u5272','Japanese discount button, red, japanese'],['🈺','u55b6','Japanese open for business button, orange, japanese'],['🉐','ideograph_advantage','Japanese bargain button, red, japanese'],['🉑','accept','Japanese acceptable button, orange, japanese'],['🌀','cyclone','cyclone, spiral, Zen, purple, swirl, storm'],['🌁','foggy','foggy, bridge, cloudy'],['🌂','closed_umbrella',', umbrella, purple, rain, closed umbrella, weather'],['🌃','night_with_stars','night, city, night with stars, scenery'],['🌄','sunrise_over_mountains','sunrise, sunrise over mountains, sun, sunset, nature, scenery'],['🌅','sunrise','sun, sunset, sunrise, scenery, nature'],['🌆','city_dusk','cityscape at dusk, city,, scenery'],['🌇','city_sunset','city, evening, sunset, scenery'],['🌈','rainbow','rainbow, pride, gay'],['🌉','bridge_at_night','night, bridge, bridge at night'],['🌊','ocean','water wave, tsunami, water, blue, ocean, art, sea, wave'],['🌋','volcano','volcano, eruption, lava, fire, geological'],['🌌','milky_way','science, milky way, galaxy, cosmos, stars, blue, nebula'],['🌍','earth_africa','africa, blue, planet, school, map, world, earth, globe, globe showing Europe-Africa, geography'],['🌎','earth_americas','blue, planet, america, school, map, globe showing Americas, world, earth, globe, geography'],['🌏','earth_asia','globe showing Asia-Australia, blue, asia, planet, school, map, world, earth, globe, australia, geography'],['🌐','globe_with_meridians','globe with meridians, blue, tech, internet, www, world, network, technology, web'],['🌑','new_moon','moon, lunar, purple, night, new moon, space, astronomy'],['🌒','waxing_crescent_moon','night, waxing crescent moon, astronomy, space, moon'],['🌓','first_quarter_moon','night, first quarter moon, astronomy, space, moon'],['🌔','waxing_gibbous_moon','night, waxing gibbous moon, astronomy, space, moon'],['🌕','full_moon','night, astronomy, full moon, space, yellow, moon'],['🌖','waning_gibbous_moon','night, astronomy, waning gibbous moon, space, moon'],['🌗','last_quarter_moon','night, astronomy, last quarter moon, space, moon'],['🌘','waning_crescent_moon','night, astronomy, waning crescent moon, space, moon'],['🌙','crescent_moon','night, astronomy, crescent moon, space, moon'],['🌚','new_moon_with_face','night, face, new moon face, astronomy, purple, space, moon'],['🌛','first_quarter_moon_with_face','night, face, astronomy, first quarter moon face, smile, space, yellow, moon'],['🌜','last_quarter_moon_with_face','night, face, astronomy, smile, last quarter moon face, space, yellow, moon'],['🌝','full_moon_with_face','night, face, full moon face, astronomy, smile, space, yellow, moon'],['🌞','sun_with_face','sun with face, night, face, astronomy, smile, space, yellow, moon'],['🌟','star2','sparkle, night, star, glowing star, yellow'],['🌠','stars','night, falling, star, cosmos, shooting star'],['🌭','hotdog','hotdog, hot dog, food'],['🌮','taco','taco, food'],['🌯','burrito','food, wrap, shawarma, burrito'],['🌰','chestnut','food, chestnut, onion'],['🌱','seedling',', green, plant, growth, seedling'],['🌲','evergreen_tree','holidays, christmas, green, evergreen tree, spruce, tree'],['🌳','deciduous_tree','oak, deciduous tree, environment, plant, nature, forest, tree, green'],['🌴','palm_tree','palm tree, vacation, palm, island, tree, beach'],['🌵','cactus','cactus, desert, green, nature, plant'],['🌷','tulip','flower, tulip, pink, nature, plant'],['🌸','cherry_blossom','pink, bloom, plant, nature, flower, sakura, cherry blossom'],['🌹','rose','flower, rose, red, nature, plant'],['🌺','hibiscus','hibiscus, pink, plant, nature, flower'],['🌻','sunflower','sunflower, nature, plant, flower, yellow'],['🌼','blossom','blossom, plant, nature, flower, white'],['🌽','corn','food, corn, ear of corn'],['🌾','ear_of_rice','food, sheaf of rice, wheat'],['🌿','herb','herb, plant'],['🍀','four_leaf_clover','lucky, four leaf clover, fortune, clover, green, plant'],['🍁','maple_leaf','maple leaf, autumn, plant, nature, leaf, fall, red, canada'],['🍂','fallen_leaf','brown, leaf, autumn, plant, nature, fall, dead leaves, fallen leaf'],['🍃','leaves','nature, green, leaf, leaf fluttering in wind, plant'],['🍄','mushroom','mushroom, nature, plant, fungi, toadstool'],['🍅','tomato','tomato, food, vegetable, red'],['🍆','eggplant','eggplant, food, vegetable, purple'],['🍇','grapes','food, fruit, grapes, grape, purple'],['🍈','melon','melon, fruit, food'],['🍉','watermelon','watermelon, fruit, food, red'],['🍊','tangerine','food, fruit, tangerine, orange'],['🍋','lemon','lemon, food, fruit, yellow'],['🍌','banana','banana, food, fruit, berry, yellow'],['🍍','pineapple','pineapple, food, fruit'],['🍎','apple','food, red apple, fruit, apple, school,, red'],['🍏','green_apple','food, fruit, green, apple, green apple'],['🍐','pear','pear, food, fruit, green'],['🍑','peach','peach, food, fruit'],['🍒','cherries','food, fruit, cherries, cherry, red'],['🍓','strawberry','strawberry, berry, fruit, food, red'],['🍔','hamburger','hamburger, america, food'],['🍕','pizza','pizza, food'],['🍖','meat_on_bone','food, meat on bone, ham'],['🍗','poultry_leg','chicken, poultry leg, food'],['🍘','rice_cracker','rice cracker, rice'],['🍙','rice_ball','onigiri, rice, rice ball, food'],['🍚','rice','food, rice, cooked rice'],['🍛','curry','food, rice, curry, curry rice'],['🍜','ramen','food, steaming bowl, ramen, noodles'],['🍝','spaghetti','food, pasta, spaghetti'],['🍞','bread','bread, food'],['🍟','fries','fries, french fries, french, food'],['🍠','sweet_potato','food, roasted, roasted sweet potato, sweet, potato'],['🍡','dango','dango, food'],['🍢','oden','oden, food'],['🍣','sushi','sushi, salmon, food'],['🍤','fried_shrimp','food, prawn, fried shrimp'],['🍥','fish_cake',', fish cake with swirl'],['🍦','icecream','desert, icecrean, soft ice cream, food'],['🍧','shaved_ice','desert, icecrean, shaved ice, food'],['🍨','ice_cream','desert, ice cream, icecrean, food'],['🍩','doughnut','desert, donut, doughnut, food'],['🍪','cookie','cookie, desert, food'],['🍫','chocolate_bar','desert, chocolate, chocolate bar, food'],['🍬','candy','candy, desert, food'],['🍭','lollipop','desert, candy, lollipop, food'],['🍮','custard','custard, food, dessert'],['🍯','honey_pot','food, honey, honey pot'],['🍰','cake','food, shortcake, cakedesert'],['🍱','bento','bento, rice, bento box, food'],['🍲','stew','food, soup, pot of food'],['🍳','cooking','food, cooking, omelette, egg'],['🍴','fork_and_knife','cutlery, food, fork and knife, fork, knife'],['🍵','tea','chai, food, drink, tea, teacup without handle'],['🍶','sake','sake, drink'],['🍷','wine_glass','food, wine glass, wine, drink'],['🍸','cocktail','food, glass, cocktail glass, drink, cocktail, martini'],['🍹','tropical_drink','drink, tropical drink, long island, food'],['🍺','beer','food, beer mug, drink, beer'],['🍻','beers','food, clinking beer mugs, drink, beer'],['🍼','baby_bottle','food, baby bottle, drink, baby, milk'],['🍾','champagne','drink, bottle with popping cork, champagne, food'],['🍿','popcorn','popcorn, food'],['🎀','ribbon','decoration, present, bow, ribbon, cute'],['🎁','gift','wrapped gift, present, christmas'],['🎂','birthday','birthday, birthday cake, cake'],['🎃','jack_o_lantern','scary, pumpkin, spooky, fall, orange, halloween, jack-o-lantern'],['🎄','christmas_tree','Christmas tree, tree, christmas, holidays'],['🎅','santa','santa, Santa Claus, christmas, holidays'],['🎆','fireworks','fireworks, party'],['🎇','sparkler','fireworks, sparkler, party'],['🎈','balloon','baloon, red, balloon'],['🎉','tada','confetti, party, party popper, celebration'],['🎊','confetti_ball','confetti, party, confetti ball, celebration'],['🎋','tanabata_tree','tanabata, tree, tanabata tree'],['🎌','crossed_flags',', crossed flags'],['🎍','bamboo','bamboo, pine decoration'],['🎎','dolls',', Japanese dolls'],['🎏','flags',', carp streamer'],['🎐','wind_chime',', wind chime'],['🎑','rice_scene',', moon viewing ceremony'],['🎒','school_satchel','school, backpack, bag'],['🎓','mortar_board','graduation, graduate, education, school, graduation cap, university'],['🎠','carousel_horse','park, carousel, carousel horse, pony'],['🎡','ferris_wheel','park, ferris, ferris wheel, wheel'],['🎢','roller_coaster','park, roller coaster, rollercoaster'],['🎣','fishing_pole_and_fish','fishing, fishing pole, fish, rod'],['🎤','microphone','microphone, speech, talk, singing'],['🎥','movie_camera','recording, movie camera, cinema, film, video, camera, content creation'],['🎦','cinema','camera, blue, recording, video, film, cinema'],['🎧','headphones','music, headphone, headphones, audio'],['🎨','art','colors, artist palette, creativity, design, painting, art, inspiration'],['🎩','tophat','hat, top hat, magic'],['🎪','circus_tent','circus, circus tent'],['🎫','ticket','ticket'],['🎬','clapper','video editing, media, video, clapper board, audiovisual'],['🎭','performing_arts','theater, performing arts, drama, masks'],['🎮','video_game','xbox, ps4, gaming, video game, playstation'],['🎯','dart','direct hit, goal, target, task'],['🎰','slot_machine','slot, casino, slot machine, games, gambling'],['🎱','8ball','billiard, games, ball, 8, eight, pool 8 ball'],['🎲','game_die','dice, luck, games, one, 1, game die'],['🎳','bowling','bowling, games, games'],['🎴','flower_playing_cards','play, card, flower playing cards'],['🎵','musical_note','note, musical note, song, music'],['🎶','notes','note, song, music, musical notes'],['🎷','saxophone','instrument, song, music, sax, saxophone'],['🎸','guitar','music, guitar, instrument, electric, song'],['🎹','musical_keyboard','instrument, song, music, piano, musical keyboard'],['🎺','trumpet','music, trumpet, instrument, song'],['🎻','violin','music, instrument, violin, sound'],['🎼','musical_score','musical score, sound, music'],['🎽','running_shirt_with_sash','clothes, running shirt, vest'],['🎾','tennis','tennis, sport'],['🎿','ski','scating, sport, skis'],['🏀','basketball','basketball, sport, orange'],['🏁','checkered_flag','finish, sport, chequered flag, race'],['🏂','snowboarder','snowboarder, snowboard, sport, snow'],['🏃','person_running','person running, sport, running'],['🏄','person_surfing','person surfing, surfing, sport'],['🏅','medal','gold, win, medal, sports medal'],['🏆','trophy','trophy, win, gold'],['🏇','horse_racing','horse racing, horse, sport, racing'],['🏈','football','american football, brown, football, sport'],['🏉','rugby_football','rugby football, football, sport'],['🏊','person_swimming','sport, swimming, person swimming'],['🏏','cricket_game','baseball, sport, cricket, cricket game'],['🏐','volleyball','white, football, volleyball, sport'],['🏑','field_hockey','hockey, field hockey, sport, field'],['🏒','hockey','hockey, ice hockey, sport'],['🏓','ping_pong','ping pong, tennis, sport'],['🥋', 'martial_arts_uniform', 'martial arts, judo'],['🏠','house','home, house, building'],['🏡','house_with_garden','building, house with garden, home, house'],['🏢','office','office building, work, building, office'],['🏣','post_office','building, post, office, Japanese post office'],['🏤','european_post_office','post office, building, post, office'],['🏥','hospital','hospital, building, health'],['🏦','bank','bank, money, building'],['🏧','atm','atm, ATM sign, blue'],['🏨','hotel','hotel, building'],['🏩','love_hotel','love, building, hotel, love hotel'],['🏪','convenience_store','store, building, shop, groceries, convenience store, convenience'],['🏫','school','school, building'],['🏬','department_store','store, building, department store'],['🏭','factory','factory, work, building'],['🏮','izakaya_lantern','lamp, red paper lantern, light'],['🏯','japanese_castle','building, Japanese castle, temple, castle, fortress'],['🏰','european_castle','temple, castle, fortress, building'],['🏴','flag_black','black flag, flag, black'],['🏸','badminton','badminton, racket, sport'],['🏹','bow_and_arrow','archery, bow and arrow, sport'],['🏺','amphora','amphora, vase'],['🐀','rat','animal, rat'],['🐁','mouse2','animal, mouse'],['🐂','ox','animal, ox'],['🐃','water_buffalo',', water buffalo'],['🐄','cow2','animal, cow'],['🐅','tiger2','animal, tiger'],['🐆','leopard','animal, leopard'],['🐇','rabbit2','animal, rabbit, bunny, hair'],['🐈','cat2','animal, cat'],['🐉','dragon','animal, dragon'],['🐊','crocodile','alagator, animal, crocodile, green'],['🐋','whale2','animal, whale, blue'],['🐌','snail','animal, snail'],['🐍','snake','animal, snake'],['🐎','racehorse','animal, horse'],['🐏','ram','animal, ram'],['🐐','goat','animal, goat'],['🐑','sheep','animal, ewe'],['🐒','monkey','animal, monkey'],['🐓','rooster','animal, rooster'],['🐔','chicken','chicken, animal'],['🐕','dog2','animal, dog'],['🐖','pig2','animal, pig'],['🐗','boar','animal, boar'],['🐘','elephant','animal, elephant'],['🐙','octopus','animal, octopus'],['🐚','shell','spiral shell, seashell, sea, beach, ocean'],['🐛','bug','animal, insect, bug'],['🐜','ant','animal, insect, ant, bug'],['🐝','bee','animal, insect, bug, honeybee'],['🐞','beetle','animal, insect, bug, lady beetle'],['🐟','fish','animal, fish'],['🐠','tropical_fish','tropical fish, animal'],['🐡','blowfish','animal, blowfish'],['🐢','turtle','animal, turtle, green'],['🐣','hatching_chick','hatching chick, animal'],['🐤','baby_chick','animal, baby chick'],['🐥','hatched_chick','animal, front-facing baby chick'],['🐦','bird','animal, bird'],['🐧','penguin','linux, animal, penguin'],['🐨','koala','animal, koala'],['🐩','poodle','animal, poodle'],['🐪','dromedary_camel','animal, camel'],['🐫','camel','animal, two-hump camel'],['🐬','dolphin','animal, dolphin'],['🐭','mouse','animal, mouse face, face'],['🐮','cow','animal, face, cow face'],['🐯','tiger','tiger face, animal, face'],['🐰','rabbit','animal, cute, rabbit face'],['🐱','cat','animal, cat face, face, cute'],['🐲','dragon_face','animal, dragon face'],['🐳','whale','animal, spouting whale'],['🐴','horse','animal, face, horse face'],['🐵','monkey_face','monkey face, animal, face'],['🐶','dog','animal, face, dog face'],['🐷','pig','animal, face, pig face'],['🐸','frog','frog, animal, face'],['🐹','hamster','animal, face, hamster'],['🐺','wolf','animal, face, wolf'],['🐻','bear','animal, face, bear'],['🐼','panda_face','animal, panda'],['🐽','pig_nose','animal, pig nose, nose'],['🐾','feet','animal, tracks, paw prints'],['👀','eyes','looking, eyes'],['👂','ear','listen, sound, ear'],['👃','nose','nose, smell'],['👄','lips','mouth'],['👅','tongue','tongue, silly, mouth'],['👆','point_up_2',', backhand index pointing up'],['👇','point_down',', backhand index pointing down'],['👈','point_left',', backhand index pointing left'],['👉','point_right',', backhand index pointing right'],['👊','punch',', oncoming fist'],['👋','wave',', waving hand'],['👌','ok_hand',', OK hand'],['👍','thumbsup',', thumbs up'],['👎','thumbsdown',', thumbs down'],['👏','clap',', clapping hands'],['👐','open_hands',', open hands'],['👑','crown',', crown'],['👒','womans_hat',', woman’s hat'],['👓','eyeglasses',', glasses'],['👔','necktie',', necktie'],['👕','shirt',', t-shirt'],['👖','jeans',', jeans'],['👗','dress',', dress'],['👘','kimono',', kimono'],['👙','bikini',', bikini'],['👚','womans_clothes',', woman’s clothes'],['👛','purse',', purse'],['👜','handbag',', handbag'],['👝','pouch',', clutch bag'],['👞','mans_shoe',', man’s shoe'],['👟','athletic_shoe',', running shoe'],['👠','high_heel',', high-heeled shoe'],['👡','sandal',', woman’s sandal'],['👢','boot',', woman’s boot'],['👣','footprints',', footprints'],['👤','bust_in_silhouette',', bust in silhouette'],['👥','busts_in_silhouette',', busts in silhouette'],['👦','boy',', boy'],['👧','girl',', girl'],['👨','man',', man'],['👩','woman',', woman'],['👪','family',', family'],['👫','couple',', woman and man holding hands'],['👬','two_men_holding_hands',', men holding hands'],['👭','two_women_holding_hands',', women holding hands'],['👮','police_officer',', police officer'],['👯','people_with_bunny_ears_partying',', people with bunny ears'],['👰','bride_with_veil',', bride with veil'],['👱','blond_haired_person',', person: blond hair'],['👲','man_with_chinese_cap',', man with skullcap'],['👳','person_wearing_turban',', person wearing turban'],['👴','older_man',', old man'],['👵','older_woman',', old woman'],['👶','baby',', baby'],['👷','construction_worker',', construction worker'],['👸','princess',', princess'],['👹','japanese_ogre',', ogre'],['👺','japanese_goblin',', goblin'],['👻','ghost','ghost, halloween'],['👼','angel',', baby angel'],['👽','alien',', alien'],['👾','space_invader',', alien monster'],['👿','imp',', angry face with horns'],['💀','skull','spooky, skull, horror, bones'],['💁','person_tipping_hand','person tipping hand, questions'],['💂','guard',', guard'],['💃','dancer',', woman dancing'],['💄','lipstick','makeup, lipstick'],['💅','nail_care','beauty, nail polish, makeup'],['💆','person_getting_massage',', person getting massage'],['💇','person_getting_haircut',', person getting haircut'],['💈','barber',', barber pole'],['💉','syringe',', syringe'],['💊','pill',', pill'],['💋','kiss',', kiss mark'],['💌','love_letter',', love letter'],['💍','ring',', ring'],['💎','gem',', gem stone'],['💏','couplekiss',', kiss'],['💐','bouquet',', bouquet'],['💑','couple_with_heart',', couple with heart'],['💒','wedding',', wedding'],['💓','heartbeat',', beating heart'],['💔','broken_heart',', broken heart'],['💕','two_hearts',', two hearts'],['💖','sparkling_heart',', sparkling heart'],['💗','heartpulse',', growing heart'],['💘','cupid',', heart with arrow'],['💙','blue_heart',', blue heart'],['💚','green_heart',', green heart'],['💛','yellow_heart',', yellow heart'],['💜','purple_heart',', purple heart'],['💝','gift_heart',', heart with ribbon'],['💞','revolving_hearts',', revolving hearts'],['💟','heart_decoration',', heart decoration'],['💠','diamond_shape_with_a_dot_inside',', diamond with a dot'],['💡','bulb',', light bulb'],['💢','anger',', anger symbol'],['💣','bomb',', bomb'],['💤','zzz',', zzz'],['💥','boom',', collision'],['💦','sweat_drops',', sweat droplets'],['💧','droplet',', droplet'],['💨','dash',', dashing away'],['💩','poop',', pile of poo'],['💪','muscle',', flexed biceps'],['💫','dizzy',', dizzy'],['💬','speech_balloon',', speech balloon'],['💭','thought_balloon',', thought balloon'],['💮','white_flower',', white flower'],['💯','100',', hundred points'],['💰','moneybag',', money bag'],['💱','currency_exchange',', currency exchange'],['💲','heavy_dollar_sign',', heavy dollar sign'],['💳','credit_card',', credit card'],['💴','yen',', yen banknote'],['💵','dollar',', dollar banknote'],['💶','euro',', euro banknote'],['💷','pound',', pound banknote'],['💸','money_with_wings',', money with wings'],['💹','chart',', chart increasing with yen'],['💺','seat',', seat'],['💻','computer',', laptop'],['💼','briefcase',', briefcase'],['💽','minidisc',', computer disk'],['💾','floppy_disk',', floppy disk'],['💿','cd',', optical disk'],['📀','dvd',', dvd'],['📁','file_folder',', file folder'],['📂','open_file_folder',', open file folder'],['📃','page_with_curl',', page with curl'],['📄','page_facing_up',', page facing up'],['📅','date',', calendar'],['📆','calendar',', tear-off calendar'],['📇','card_index',', card index'],['📈','chart_with_upwards_trend',', chart increasing'],['📉','chart_with_downwards_trend',', chart decreasing'],['📊','bar_chart',', bar chart'],['📋','clipboard',', clipboard'],['📌','pushpin',', pushpin'],['📍','round_pushpin',', round pushpin'],['📎','paperclip',', paperclip'],['📏','straight_ruler',', straight ruler'],['📐','triangular_ruler',', triangular ruler'],['📑','bookmark_tabs',', bookmark tabs'],['📒','ledger',', ledger'],['📓','notebook',', notebook'],['📔','notebook_with_decorative_cover',', notebook with decorative cover'],['📕','closed_book',', closed book'],['📖','book',', open book'],['📗','green_book',', green book'],['📘','blue_book',', blue book'],['📙','orange_book',', orange book'],['📚','books','books, study, school'],['📛','name_badge',', name badge'],['📜','scroll',', scroll'],['📝','pencil','pencil, memo, note, school, study'],['📞','telephone_receiver','call, telephone receiver, phone'],['📟','pager',', pager'],['📠','fax',', fax machine'],['📡','satellite',', satellite antenna'],['📢','loudspeaker',', loudspeaker'],['📣','mega',', megaphone'],['📤','outbox_tray',', outbox tray'],['📥','inbox_tray',', inbox tray'],['📦','package',', package'],['📧','e-mail','mail, e-mail'],['📨','incoming_envelope','mail, incoming envelope'],['📩','envelope_with_arrow','mail, envelope with arrow'],['📪','mailbox_closed','closed mailbox with lowered flag, mail'],['📫','mailbox','mail, closed mailbox with raised flag'],['📬','mailbox_with_mail','mail, open mailbox with raised flag'],['📭','mailbox_with_no_mail','mail, open mailbox with lowered flag'],['📮','postbox',', postbox'],['📯','postal_horn',', postal horn'],['📰','newspaper',', newspaper'],['📱','iphone',', mobile phone'],['📲','calling',', mobile phone with arrow'],['📳','vibration_mode',', vibration mode'],['📴','mobile_phone_off',', mobile phone off'],['📵','no_mobile_phones',', no mobile phones'],['📶','signal_strength',', antenna bars'],['📷','camera','photo, photography, camera'],['📸','camera_with_flash','camera with flash, photo, photography'],['📹','video_camera',', video camera'],['📺','tv',', television'],['📻','radio',', radio'],['📼','vhs',', videocassette'],['📿','prayer_beads',', prayer beads'],['🔀','twisted_rightwards_arrows',', shuffle tracks button'],['🔁','repeat',', repeat button'],['🔂','repeat_one',', repeat single button'],['🔃','arrows_clockwise',', clockwise vertical arrows'],['🔄','arrows_counterclockwise',', counterclockwise arrows button'],['🔅','low_brightness',', dim button'],['🔆','high_brightness',', bright button'],['🔇','mute',', muted speaker'],['🔈','speaker',', speaker low volume'],['🔉','sound',', speaker medium volume'],['🔊','loud_sound',', speaker high volume'],['🔋','battery',', battery'],['🔌','electric_plug',', electric plug'],['🔍','mag','magnifying glass tilted left, search'],['🔎','mag_right','search, magnifying glass tilted right'],['🔏','lock_with_ink_pen',', locked with pen'],['🔐','closed_lock_with_key',', locked with key'],['🔑','key',', key'],['🔒','lock',', locked'],['🔓','unlock',', unlocked'],['🔔','bell',', bell'],['🔕','no_bell',', bell with slash'],['🔖','bookmark',', bookmark'],['🔗','link',', link'],['🔘','radio_button',', radio button'],['🔙','back',', BACK arrow'],['🔚','end',', END arrow'],['🔛','on',', ON! arrow'],['🔜','soon',', SOON arrow'],['🔝','top',', TOP arrow'],['🔞','underage',', no one under eighteen'],['🔟','keycap_ten',', keycap: 10'],['🔠','capital_abcd',', input latin uppercase'],['🔡','abcd',', input latin lowercase'],['🔢','1234',', input numbers'],['🔣','symbols',', input symbols'],['🔤','abc',', input latin letters'],['🔥','fire',', fire'],['🔦','flashlight',', flashlight'],['🔧','wrench',', wrench'],['🔨','hammer',', hammer'],['🔩','nut_and_bolt',', nut and bolt'],['🔪','knife',', kitchen knife'],['🔫','gun',', pistol'],['🔬','microscope',', microscope'],['🔭','telescope',', telescope'],['🔮','crystal_ball',', crystal ball'],['🔯','six_pointed_star',', dotted six-pointed star'],['🔰','beginner',', Japanese symbol for beginner'],['🔱','trident',', trident emblem'],['🔲','black_square_button',', black square button'],['🔳','white_square_button',', white square button'],['🔴','red_circle',', red circle'],['🔵','blue_circle',', blue circle'],['🔶','large_orange_diamond',', large orange diamond'],['🔷','large_blue_diamond',', large blue diamond'],['🔸','small_orange_diamond',', small orange diamond'],['🔹','small_blue_diamond',', small blue diamond'],['🔺','small_red_triangle',', red triangle pointed up'],['🔻','small_red_triangle_down',', red triangle pointed down'],['🔼','arrow_up_small',', upwards button'],['🔽','arrow_down_small',', downwards button'],['🕋','kaaba',', kaaba'],['🕌','mosque',', mosque'],['🕍','synagogue',', synagogue'],['🕎','menorah',', menorah'],['🕐','clock1',', one o’clock'],['🕑','clock2',', two o’clock'],['🕒','clock3',', three o’clock'],['🕓','clock4',', four o’clock'],['🕔','clock5',', five o’clock'],['🕕','clock6',', six o’clock'],['🕖','clock7',', seven o’clock'],['🕗','clock8',', eight o’clock'],['🕘','clock9',', nine o’clock'],['🕙','clock10',', ten o’clock'],['🕚','clock11',', eleven o’clock'],['🕛','clock12',', twelve o’clock'],['🕜','clock130',', one-thirty'],['🕝','clock230',', two-thirty'],['🕞','clock330',', three-thirty'],['🕟','clock430',', four-thirty'],['🕠','clock530',', five-thirty'],['🕡','clock630',', six-thirty'],['🕢','clock730',', seven-thirty'],['🕣','clock830',', eight-thirty'],['🕤','clock930',', nine-thirty'],['🕥','clock1030',', ten-thirty'],['🕦','clock1130',', eleven-thirty'],['🕧','clock1230',', twelve-thirty'],['🖕','middle_finger',', middle finger'],['🖖','vulcan',', vulcan salute'],['🗻','mount_fuji',', mount fuji'],['🗼','tokyo_tower',', Tokyo tower'],['🗽','statue_of_liberty',', Statue of Liberty'],['🗾','japan',', map of Japan'],['🗿','moyai',', moai'],['😀','grinning',', grinning face'],['😁','grin',', beaming face with smiling eyes'],['😂','joy',', face with tears of joy'],['😃','smiley',', grinning face with big eyes'],['😄','smile',', grinning face with smiling eyes'],['😅','sweat_smile',', grinning face with sweat'],['😆','laughing',', grinning squinting face'],['😇','innocent',', smiling face with halo'],['😈','smiling_imp',', smiling face with horns'],['😉','wink',', winking face'],['😊','blush',', smiling face with smiling eyes'],['😋','yum',', face savoring food'],['😌','relieved',', relieved face'],['😍','heart_eyes',', smiling face with heart-eyes'],['😎','sunglasses',', smiling face with sunglasses'],['😏','smirk',', smirking face'],['😐','neutral_face',', neutral face'],['😑','expressionless',', expressionless face'],['😒','unamused',', unamused face'],['😓','sweat',', downcast face with sweat'],['😔','pensive',', pensive face'],['😕','confused',', confused face'],['😖','confounded',', confounded face'],['😗','kissing',', kissing face'],['😘','kissing_heart',', face blowing a kiss'],['😙','kissing_smiling_eyes',', kissing face with smiling eyes'],['😚','kissing_closed_eyes',', kissing face with closed eyes'],['😛','stuck_out_tongue',', face with tongue'],['😜','stuck_out_tongue_winking_eye',', winking face with tongue'],['😝','stuck_out_tongue_closed_eyes',', squinting face with tongue'],['😞','disappointed',', disappointed face'],['😟','worried',', worried face'],['😠','angry',', angry face'],['😡','rage',', pouting face'],['😢','cry',', crying face'],['😣','persevere',', persevering face'],['😤','triumph',', face with steam from nose'],['😥','disappointed_relieved',', sad but relieved face'],['😦','frowning',', frowning face with open mouth'],['😧','anguished',', anguished face'],['😨','fearful',', fearful face'],['😩','weary',', weary face'],['😪','sleepy',', sleepy face'],['😫','tired_face',', tired face'],['😬','grimacing',', grimacing face'],['😭','sob',', loudly crying face'],['😮','open_mouth',', face with open mouth'],['😯','hushed',', hushed face'],['😰','cold_sweat',', anxious face with sweat'],['😱','scream',', face screaming in fear'],['😲','astonished',', astonished face'],['😳','flushed',', flushed face'],['😴','sleeping',', sleeping face'],['😵','dizzy_face',', dizzy face'],['😶','no_mouth',', face without mouth'],['😷','mask',', face with medical mask'],['😸','smile_cat',', grinning cat with smiling eyes'],['😹','joy_cat',', cat with tears of joy'],['😺','smiley_cat','grinning cat, kitty'],['😻','heart_eyes_cat',', smiling cat with heart-eyes'],['😼','smirk_cat',', cat with wry smile'],['😽','kissing_cat',', kissing cat'],['😾','pouting_cat',', pouting cat'],['😿','crying_cat_face',', crying cat'],['🙀','scream_cat',', weary cat'],['🙁','slight_frown',', slightly frowning face'],['🙂','slight_smile',', slightly smiling face'],['🙃','upside_down',', upside-down face'],['🙄','rolling_eyes',', face with rolling eyes'],['🙅','person_gesturing_no',', person gesturing NO'],['🙆','person_gesturing_ok',', person gesturing OK'],['🙇','person_bowing',', person bowing'],['🙈','see_no_evil',', see-no-evil monkey'],['🙉','hear_no_evil',', hear-no-evil monkey'],['🙊','speak_no_evil',', speak-no-evil monkey'],['🙋','person_raising_hand',', person raising hand'],['🙌','raised_hands',', raising hands'],['🙍','person_frowning',', person frowning'],['🙎','person_pouting',', person pouting'],['🙏','pray',', folded hands'],['🚀','rocket',', rocket'],['🚁','helicopter',', helicopter'],['🚂','steam_locomotive',', locomotive'],['🚃','railway_car',', railway car'],['🚄','bullettrain_side',', high-speed train'],['🚅','bullettrain_front',', bullet train'],['🚆','train2',', train'],['🚇','metro',', metro'],['🚈','light_rail',', light rail'],['🚉','station',', station'],['🚊','tram',', tram'],['🚋','train',', tram car'],['🚌','bus',', bus'],['🚍','oncoming_bus',', oncoming bus'],['🚎','trolleybus',', trolleybus'],['🚏','busstop',', bus stop'],['🚐','minibus',', minibus'],['🚑','ambulance',', ambulance'],['🚒','fire_engine',', fire engine'],['🚓','police_car',', police car'],['🚔','oncoming_police_car',', oncoming police car'],['🚕','taxi',', taxi'],['🚖','oncoming_taxi',', oncoming taxi'],['🚗','red_car',', automobile'],['🚘','oncoming_automobile',', oncoming automobile'],['🚙','blue_car',', sport utility vehicle'],['🚚','truck',', delivery truck'],['🚛','articulated_lorry',', articulated lorry'],['🚜','tractor',', tractor'],['🚝','monorail',', monorail'],['🚞','mountain_railway',', mountain railway'],['🚟','suspension_railway',', suspension railway'],['🚠','mountain_cableway',', mountain cableway'],['🚡','aerial_tramway',', aerial tramway'],['🚢','ship',', ship'],['🚣','person_rowing_boat',', person rowing boat'],['🚤','speedboat',', speedboat'],['🚥','traffic_light',', horizontal traffic light'],['🚦','vertical_traffic_light',', vertical traffic light'],['🚧','construction',', construction'],['🚨','rotating_light',', police car light'],['🚩','triangular_flag_on_post',', triangular flag'],['🚪','door',', door'],['🚫','no_entry_sign',', prohibited'],['🚬','smoking',', cigarette'],['🚭','no_smoking',', no smoking'],['🚮','put_litter_in_its_place',', litter in bin sign'],['🚯','do_not_litter',', no littering'],['🚰','potable_water',', potable water'],['🚱','non-potable_water',', non-potable water'],['🚲','bike',', bicycle'],['🚳','no_bicycles',', no bicycles'],['🚴','person_biking',', person biking'],['🚵','person_mountain_biking',', person mountain biking'],['🚶','person_walking',', person walking'],['🚷','no_pedestrians',', no pedestrians'],['🚸','children_crossing',', children crossing'],['🚹','mens',', men’s room'],['🚺','womens',', women’s room'],['🚻','restroom',', restroom'],['🚼','baby_symbol',', baby symbol'],['🚽','toilet',', toilet'],['🚾','wc',', water closet'],['🚿','shower',', shower'],['🛀','bath',', person taking bath'],['🛁','bathtub',', bathtub'],['🛂','passport_control',', passport control'],['🛃','customs',', customs'],['🛄','baggage_claim',', baggage claim'],['🛅','left_luggage',', left luggage'],['🛌','sleeping_accommodation',', person in bed'],['🛐','place_of_worship',', place of worship'],['🛫','airplane_departure',', airplane departure'],['🛬','airplane_arriving',', airplane arrival'],['🤐','zipper_mouth',', zipper-mouth face'],['🤑','money_mouth',', money-mouth face'],['🤒','thermometer_face',', face with thermometer'],['🤓','nerd',', nerd face'],['🤔','thinking',', thinking face'],['🤕','head_bandage',', face with head-bandage'],['🤖','robot','robot, electronics, AI, artificial intelligence, tech, technology'],['🤗','hugging','hugging face, AI, artificial intelligence'],['🤘','metal','hand, rock, sign of the horns'],['🦀','crab','sea creature, crab, animal, sea, seafood'],['🦁','lion_face','animal, lion'],['🦂','scorpion','animal, scorpion'],['🦃','turkey','turkey, bird,, thanksgiving'],['🦄','unicorn','magic, fantasy, rainbow, unicorn'],['🧀','cheese','food, mouse, cheese wedge'],['🇦🇨','flag_ac','flags, flag: Ascension Island, flag'],['🇦🇩','flag_ad','flag: Andorra, flags, flag'],['🇦🇪','flag_ae','flags, flag: United Arab Emirates, flag'],['🇦🇫','flag_af','flags, flag, flag: Afghanistan'],['🇦🇬','flag_ag','flag: Antigua & Barbuda, flags, flag'],['🇦🇮','flag_ai','flags, flag, flag: Anguilla'],['🇦🇱','flag_al','flag: Albania, flags, flag'],['🇦🇲','flag_am','flags, flag: Armenia, flag'],['🇦🇴','flag_ao','flags, flag, flag: Angola'],['🇦🇶','flag_aq','flag: Antarctica, flags, flag'],['🇦🇷','flag_ar','flags, flag: Argentina, flag'],['🇦🇸','flag_as','flags, flag: American Samoa, flag'],['🇦🇹','flag_at','flags, flag, flag: Austria'],['🇦🇺','flag_au','flags, flag, flag: Australia'],['🇦🇼','flag_aw','flag: Aruba, flags, flag'],['🇦🇽','flag_ax','flag: Åland Islands, flags, flag'],['🇦🇿','flag_az','flags, flag, flag: Azerbaijan'],['🇧🇦','flag_ba','flag: Bosnia & Herzegovina, flags, flag'],['🇧🇧','flag_bb','flag: Barbados, flags, flag'],['🇧🇩','flag_bd','flags, flag, flag: Bangladesh'],['🇧🇪','flag_be','flags, flag, flag: Belgium'],['🇧🇫','flag_bf','flags, flag: Burkina Faso, flag'],['🇧🇬','flag_bg','flag: Bulgaria, flags, flag'],['🇧🇭','flag_bh','flags, flag: Bahrain, flag'],['🇧🇮','flag_bi','flag: Burundi, flags, flag'],['🇧🇯','flag_bj','flag: Benin, flags, flag'],['🇧🇱','flag_bl','flags, flag: St. Barthélemy, flag'],['🇧🇲','flag_bm','flags, flag: Bermuda, flag'],['🇧🇳','flag_bn','flags, flag: Brunei, flag'],['🇧🇴','flag_bo','flag: Bolivia, flags, flag'],['🇧🇶','flag_bq','flags, flag: Caribbean Netherlands, flag'],['🇧🇷','flag_br','flag: Brazil, flags, flag'],['🇧🇸','flag_bs','flag: Bahamas, flags, flag'],['🇧🇹','flag_bt','flags, flag: Bhutan, flag'],['🇧🇻','flag_bv','flag: Bouvet Island, flags, flag'],['🇧🇼','flag_bw','flags, flag, flag: Botswana'],['🇧🇾','flag_by','flags, flag, flag: Belarus'],['🇧🇿','flag_bz','flag: Belize, flags, flag'],['🇨🇦','flag_ca','flag: Canada, flags, flag'],['🇨🇨','flag_cc','flags, flag: Cocos (Keeling) Islands, flag'],['🇨🇩','flag_cd','flag: Congo - Kinshasa, flags, flag'],['🇨🇫','flag_cf','flag: Central African Republic, flags, flag'],['🇨🇬','flag_cg','flags, flag: Congo - Brazzaville, flag'],['🇨🇭','flag_ch','flags, flag: Switzerland, flag'],['🇨🇮','flag_ci','flags, flag: Côte d’Ivoire, flag'],['🇨🇰','flag_ck','flag: Cook Islands, flags, flag'],['🇨🇱','flag_cl','flag: Chile, flags, flag'],['🇨🇲','flag_cm','flag: Cameroon, flags, flag'],['🇨🇳','flag_cn','flags, flag, flag: China'],['🇨🇴','flag_co','flags, flag: Colombia, flag'],['🇨🇵','flag_cp','flags, flag, flag: Clipperton Island'],['🇨🇷','flag_cr','flag: Costa Rica, flags, flag'],['🇨🇺','flag_cu','flag: Cuba, flags, flag'],['🇨🇻','flag_cv','flags, flag: Cape Verde, flag'],['🇨🇼','flag_cw','flag: Curaçao, flags, flag'],['🇨🇽','flag_cx','flags, flag: Christmas Island, flag'],['🇨🇾','flag_cy','flags, flag: Cyprus, flag'],['🇨🇿','flag_cz','flags, flag, flag: Czechia'],['🇩🇪','flag_de','flags, flag, flag: Germany'],['🇩🇬','flag_dg','flag: Diego Garcia, flags, flag'],['🇩🇯','flag_dj','flag: Djibouti, flags, flag'],['🇩🇰','flag_dk','flags, flag, flag: Denmark'],['🇩🇲','flag_dm','flags, flag: Dominica, flag'],['🇩🇴','flag_do','flags, flag: Dominican Republic, flag'],['🇩🇿','flag_dz','flag: Algeria, flags, flag'],['🇪🇦','flag_ea','flags, flag: Ceuta & Melilla, flag'],['🇪🇨','flag_ec','flag: Ecuador, flags, flag'],['🇪🇪','flag_ee','flags, flag, flag: Estonia'],['🇪🇬','flag_eg','flag: Egypt, flags, flag'],['🇪🇭','flag_eh','flags, flag: Western Sahara, flag'],['🇪🇷','flag_er','flags, flag, flag: Eritrea'],['🇪🇸','flag_es','flags, flag: Spain, flag'],['🇪🇹','flag_et','flags, flag: Ethiopia, flag'],['🇪🇺','flag_eu','flags, flag: European Union, flag'],['🇫🇮','flag_fi','flag: Finland, flags, flag'],['🇫🇯','flag_fj','flags, flag, flag: Fiji'],['🇫🇰','flag_fk','flags, flag: Falkland Islands, flag'],['🇫🇲','flag_fm','flags, flag: Micronesia, flag'],['🇫🇴','flag_fo','flags, flag: Faroe Islands, flag'],['🇫🇷','flag_fr','flag: France, flags, flag'],['🇬🇦','flag_ga','flags, flag: Gabon, flag'],['🇬🇧','flag_gb','flag: United Kingdom, flags, flag'],['🇬🇩','flag_gd','flag: Grenada, flags, flag'],['🇬🇪','flag_ge','flags, flag, flag: Georgia'],['🇬🇫','flag_gf','flags, flag, flag: French Guiana'],['🇬🇬','flag_gg','flag: Guernsey, flags, flag'],['🇬🇭','flag_gh','flag: Ghana, flags, flag'],['🇬🇮','flag_gi','flags, flag, flag: Gibraltar'],['🇬🇱','flag_gl','flags, flag: Greenland, flag'],['🇬🇲','flag_gm','flag: Gambia, flags, flag'],['🇬🇳','flag_gn','flags, flag: Guinea, flag'],['🇬🇵','flag_gp','flags, flag: Guadeloupe, flag'],['🇬🇶','flag_gq','flags, flag, flag: Equatorial Guinea'],['🇬🇷','flag_gr','flag: Greece, flags, flag'],['🇬🇸','flag_gs','flag: South Georgia & South Sandwich Islands, flags, flag'],['🇬🇹','flag_gt','flags, flag: Guatemala, flag'],['🇬🇺','flag_gu','flag: Guam, flags, flag'],['🇬🇼','flag_gw','flag: Guinea-Bissau, flags, flag'],['🇬🇾','flag_gy','flag: Guyana, flags, flag'],['🇭🇰','flag_hk','flag: Hong Kong SAR China, flags, flag'],['🇭🇲','flag_hm','flags, flag, flag: Heard & McDonald Islands'],['🇭🇳','flag_hn','flags, flag, flag: Honduras'],['🇭🇷','flag_hr','flags, flag: Croatia, flag'],['🇭🇹','flag_ht','flags, flag: Haiti, flag'],['🇭🇺','flag_hu','flags, flag: Hungary, flag'],['🇮🇨','flag_ic','flags, flag, flag: Canary Islands'],['🇮🇩','flag_id','flags, flag: Indonesia, flag'],['🇮🇪','flag_ie','flags, flag: Ireland, flag'],['🇮🇱','flag_il','flags, flag: Israel, flag'],['🇮🇲','flag_im','flag: Isle of Man, flags, flag'],['🇮🇳','flag_in','flags, flag, flag: India'],['🇮🇴','flag_io','flags, flag: British Indian Ocean Territory, flag'],['🇮🇶','flag_iq','flag: Iraq, flags, flag'],['🇮🇷','flag_ir','flags, flag, flag: Iran'],['🇮🇸','flag_is','flags, flag: Iceland, flag'],['🇮🇹','flag_it','flags, flag: Italy, flag'],['🇯🇪','flag_je','flags, flag, flag: Jersey'],['🇯🇲','flag_jm','flags, flag, flag: Jamaica'],['🇯🇴','flag_jo','flag: Jordan, flags, flag'],['🇯🇵','flag_jp','flags, flag: Japan, flag'],['🇰🇪','flag_ke','flag: Kenya, flags, flag'],['🇰🇬','flag_kg','flag: Kyrgyzstan, flags, flag'],['🇰🇭','flag_kh','flag: Cambodia, flags, flag'],['🇰🇮','flag_ki','flag: Kiribati, flags, flag'],['🇰🇲','flag_km','flags, flag, flag: Comoros'],['🇰🇳','flag_kn','flags, flag: St. Kitts & Nevis, flag'],['🇰🇵','flag_kp','flag: North Korea, flags, flag'],['🇰🇷','flag_kr','flags, flag: South Korea, flag'],['🇰🇼','flag_kw','flags, flag, flag: Kuwait'],['🇰🇾','flag_ky','flags, flag: Cayman Islands, flag'],['🇰🇿','flag_kz','flags, flag: Kazakhstan, flag'],['🇱🇦','flag_la','flags, flag, flag: Laos'],['🇱🇧','flag_lb','flags, flag, flag: Lebanon'],['🇱🇨','flag_lc','flag: St. Lucia, flags, flag'],['🇱🇮','flag_li','flags, flag, flag: Liechtenstein'],['🇱🇰','flag_lk','flags, flag, flag: Sri Lanka'],['🇱🇷','flag_lr','flag: Liberia, flags, flag'],['🇱🇸','flag_ls','flag: Lesotho, flags, flag'],['🇱🇹','flag_lt','flags, flag: Lithuania, flag'],['🇱🇺','flag_lu','flags, flag, flag: Luxembourg'],['🇱🇻','flag_lv','flag: Latvia, flags, flag'],['🇱🇾','flag_ly','flags, flag: Libya, flag'],['🇲🇦','flag_ma','flags, flag, flag: Morocco'],['🇲🇨','flag_mc','flags, flag, flag: Monaco'],['🇲🇩','flag_md','flag: Moldova, flags, flag'],['🇲🇪','flag_me','flag: Montenegro, flags, flag'],['🇲🇫','flag_mf','flags, flag, flag: St. Martin'],['🇲🇬','flag_mg','flags, flag, flag: Madagascar'],['🇲🇭','flag_mh','flags, flag: Marshall Islands, flag'],['🇲🇰','flag_mk','flags, flag, flag: North Macedonia'],['🇲🇱','flag_ml','flag: Mali, flags, flag'],['🇲🇲','flag_mm','flags, flag: Myanmar (Burma), flag'],['🇲🇳','flag_mn','flag: Mongolia, flags, flag'],['🇲🇴','flag_mo','flags, flag: Macao SAR China, flag'],['🇲🇵','flag_mp','flags, flag: Northern Mariana Islands, flag'],['🇲🇶','flag_mq','flags, flag: Martinique, flag'],['🇲🇷','flag_mr','flag: Mauritania, flags, flag'],['🇲🇸','flag_ms','flags, flag, flag: Montserrat'],['🇲🇹','flag_mt','flags, flag: Malta, flag'],['🇲🇺','flag_mu','flags, flag, flag: Mauritius'],['🇲🇻','flag_mv','flag: Maldives, flags, flag'],['🇲🇼','flag_mw','flags, flag: Malawi, flag'],['🇲🇽','flag_mx','flag: Mexico, flags, flag'],['🇲🇾','flag_my','flags, flag: Malaysia, flag'],['🇲🇿','flag_mz','flags, flag: Mozambique, flag'],['🇳🇦','flag_na','flags, flag, flag: Namibia'],['🇳🇨','flag_nc','flags, flag, flag: New Caledonia'],['🇳🇪','flag_ne','flags, flag: Niger, flag'],['🇳🇫','flag_nf','flags, flag, flag: Norfolk Island'],['🇳🇬','flag_ng','flags, flag: Nigeria, flag'],['🇳🇮','flag_ni','flags, flag: Nicaragua, flag'],['🇳🇱','flag_nl','flags, flag, flag: Netherlands'],['🇳🇴','flag_no','flag: Norway, flags, flag'],['🇳🇵','flag_np','flags, flag, flag: Nepal'],['🇳🇷','flag_nr','flags, flag: Nauru, flag'],['🇳🇺','flag_nu','flag: Niue, flags, flag'],['🇳🇿','flag_nz','flag: New Zealand, flags, flag'],['🇴🇲','flag_om','flags, flag: Oman, flag'],['🇵🇦','flag_pa','flags, flag, flag: Panama'],['🇵🇪','flag_pe','flag: Peru, flags, flag'],['🇵🇫','flag_pf','flag: French Polynesia, flags, flag'],['🇵🇬','flag_pg','flags, flag: Papua New Guinea, flag'],['🇵🇭','flag_ph','flags, flag, flag: Philippines'],['🇵🇰','flag_pk','flag: Pakistan, flags, flag'],['🇵🇱','flag_pl','flags, flag: Poland, flag'],['🇵🇲','flag_pm','flags, flag, flag: St. Pierre & Miquelon'],['🇵🇳','flag_pn','flags, flag, flag: Pitcairn Islands'],['🇵🇷','flag_pr','flag: Puerto Rico, flags, flag'],['🇵🇸','flag_ps','flags, flag: Palestinian Territories, flag'],['🇵🇹','flag_pt','flag: Portugal, flags, flag'],['🇵🇼','flag_pw','flag: Palau, flags, flag'],['🇵🇾','flag_py','flag: Paraguay, flags, flag'],['🇶🇦','flag_qa','flag: Qatar, flags, flag'],['🇷🇪','flag_re','flags, flag, flag: Réunion'],['🇷🇴','flag_ro','flags, flag, flag: Romania'],['🇷🇸','flag_rs','flags, flag: Serbia, flag'],['🇷🇺','flag_ru','flags, flag, flag: Russia'],['🇷🇼','flag_rw','flags, flag, flag: Rwanda'],['🇸🇦','flag_sa','flags, flag, flag: Saudi Arabia'],['🇸🇧','flag_sb','flag: Solomon Islands, flags, flag'],['🇸🇨','flag_sc','flags, flag: Seychelles, flag'],['🇸🇩','flag_sd','flags, flag, flag: Sudan'],['🇸🇪','flag_se','flag: Sweden, flags, flag'],['🇸🇬','flag_sg','flags, flag, flag: Singapore'],['🇸🇭','flag_sh','flags, flag, flag: St. Helena'],['🇸🇮','flag_si','flags, flag: Slovenia, flag'],['🇸🇯','flag_sj','flag: Svalbard & Jan Mayen, flags, flag'],['🇸🇰','flag_sk','flags, flag, flag: Slovakia'],['🇸🇱','flag_sl','flag: Sierra Leone, flags, flag'],['🇸🇲','flag_sm','flags, flag: San Marino, flag'],['🇸🇳','flag_sn','flags, flag: Senegal, flag'],['🇸🇴','flag_so','flags, flag, flag: Somalia'],['🇸🇷','flag_sr','flag: Suriname, flags, flag'],['🇸🇸','flag_ss','flags, flag: South Sudan, flag'],['🇸🇹','flag_st','flags, flag: São Tomé & Príncipe, flag'],['🇸🇻','flag_sv','flags, flag: El Salvador, flag'],['🇸🇽','flag_sx','flags, flag, flag: Sint Maarten'],['🇸🇾','flag_sy','flags, flag: Syria, flag'],['🇸🇿','flag_sz','flags, flag: Eswatini, flag'],['🇹🇦','flag_ta','flags, flag: Tristan da Cunha, flag'],['🇹🇨','flag_tc','flags, flag, flag: Turks & Caicos Islands'],['🇹🇩','flag_td','flags, flag: Chad, flag'],['🇹🇫','flag_tf','flag: French Southern Territories, flags, flag'],['🇹🇬','flag_tg','flags, flag, flag: Togo'],['🇹🇭','flag_th','flag: Thailand, flags, flag'],['🇹🇯','flag_tj','flag: Tajikistan, flags, flag'],['🇹🇰','flag_tk','flags, flag: Tokelau, flag'],['🇹🇱','flag_tl','flags, flag: Timor-Leste, flag'],['🇹🇲','flag_tm','flags, flag, flag: Turkmenistan'],['🇹🇳','flag_tn','flag: Tunisia, flags, flag'],['🇹🇴','flag_to','flags, flag, flag: Tonga'],['🇹🇷','flag_tr','flags, flag: Turkey, flag'],['🇹🇹','flag_tt','flags, flag, flag: Trinidad & Tobago'],['🇹🇻','flag_tv','flag: Tuvalu, flags, flag'],['🇹🇼','flag_tw','flag: Taiwan, flags, flag'],['🇹🇿','flag_tz','flag: Tanzania, flags, flag'],['🇺🇦','flag_ua','flags, flag, flag: Ukraine'],['🇺🇬','flag_ug','flags, flag: Uganda, flag'],['🇺🇲','flag_um','flags, flag, flag: U.S. Outlying Islands'],['🇺🇸','flag_us','flags, flag, flag: United States'],['🇺🇾','flag_uy','flags, flag, flag: Uruguay'],['🇺🇿','flag_uz','flags, flag, flag: Uzbekistan'],['🇻🇦','flag_va','flags, flag: Vatican City, flag'],['🇻🇨','flag_vc','flag: St. Vincent & Grenadines, flags, flag'],['🇻🇪','flag_ve','flags, flag, flag: Venezuela'],['🇻🇬','flag_vg','flag: British Virgin Islands, flags, flag'],['🇻🇮','flag_vi','flag: U.S. Virgin Islands, flags, flag'],['🇻🇳','flag_vn','flags, flag: Vietnam, flag'],['🇻🇺','flag_vu','flags, flag: Vanuatu, flag'],['🇼🇫','flag_wf','flag: Wallis & Futuna, flags, flag'],['🇼🇸','flag_ws','flag: Samoa, flags, flag'],['🇽🇰','flag_xk','flags, flag, flag: Kosovo'],['🇾🇪','flag_ye','flags, flag, flag: Yemen'],['🇾🇹','flag_yt','flags, flag, flag: Mayotte'],['🇿🇦','flag_za','flags, flag: South Africa, flag'],['🇿🇲','flag_zm','flags, flag: Zambia, flag'],['🇿🇼','flag_zw','flags, flag: Zimbabwe, flag'],['🏳️‍🌈','rainbow_flag','flag, rainbow flag, pride, gay, flags'],['🏳️‍⚧️','transgender_flag','trans, pride, flag, flags']];} \ No newline at end of file From 5bbd881f01c90defe81987bb68c6b539eade6404 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Tue, 4 Mar 2025 15:21:00 +0100 Subject: [PATCH 020/127] Fixed common issues with split views and glance --- .../base/content/zen-styles/zen-decks.css | 12 +- .../content/zen-styles/zen-workspaces.css | 1 + .../base/zen-components/ZenCompactMode.mjs | 1 + .../base/zen-components/ZenGlanceManager.mjs | 7 +- .../base/zen-components/ZenViewSplitter.mjs | 143 +++++++++--------- 5 files changed, 81 insertions(+), 83 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-decks.css b/src/browser/base/content/zen-styles/zen-decks.css index 40bc938eb..79200caec 100644 --- a/src/browser/base/content/zen-styles/zen-decks.css +++ b/src/browser/base/content/zen-styles/zen-decks.css @@ -222,17 +222,6 @@ z-index: 100; transform: translateX(-50%); pointer-events: none; - - &::before { - content: ''; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 100%; - height: 6px; - background: var(--zen-colors-border); - } } .zen-view-splitter-header { @@ -244,6 +233,7 @@ background-color: light-dark(rgba(255, 255, 255, 1), rgba(0, 0, 0, 1)); box-shadow: 0 0 0 1px var(--button-primary-border-color); gap: 0.8rem; + transform: translateX(-50%); } :root:not([inDOMFullscreen='true']) .browserSidebarContainer:hover .zen-view-splitter-header-container, diff --git a/src/browser/base/content/zen-styles/zen-workspaces.css b/src/browser/base/content/zen-styles/zen-workspaces.css index 5b9ce55d5..9a13ac4da 100644 --- a/src/browser/base/content/zen-styles/zen-workspaces.css +++ b/src/browser/base/content/zen-styles/zen-workspaces.css @@ -489,6 +489,7 @@ & .zen-current-workspace-indicator-icon { font-size: 12px; + line-height: 1; } .zen-current-workspace-indicator-name { diff --git a/src/browser/base/zen-components/ZenCompactMode.mjs b/src/browser/base/zen-components/ZenCompactMode.mjs index a88b25032..94f86472e 100644 --- a/src/browser/base/zen-components/ZenCompactMode.mjs +++ b/src/browser/base/zen-components/ZenCompactMode.mjs @@ -202,6 +202,7 @@ var gZenCompactModeManager = { this._animating = false; this.sidebar.style.removeProperty('visibility'); this.sidebar.style.removeProperty('transition'); + thhis.sidebar.style.removeProperty('opacity'); }, 300); }); }); diff --git a/src/browser/base/zen-components/ZenGlanceManager.mjs b/src/browser/base/zen-components/ZenGlanceManager.mjs index d075beae4..578eb8183 100644 --- a/src/browser/base/zen-components/ZenGlanceManager.mjs +++ b/src/browser/base/zen-components/ZenGlanceManager.mjs @@ -468,7 +468,6 @@ owner && owner.pinned && this._lazyPref.SHOULD_OPEN_EXTERNAL_TABS_IN_GLANCE && - owner.linkedBrowser?.docShellIsActive && owner.linkedBrowser?.browsingContext?.isAppTab && this.tabDomainsDiffer(owner, uri) && Services.prefs.getBoolPref('zen.glance.enabled', true) @@ -483,7 +482,11 @@ try { if (this.shouldOpenTabInGlance(tab, uri)) { const browserRect = gBrowser.tabbox.getBoundingClientRect(); - this.openGlance({ url: undefined, x: browserRect.width / 2, y: browserRect.height / 2, width: 0, height: 0 }); + this.openGlance( + { url: undefined, x: browserRect.width / 2, y: browserRect.height / 2, width: 0, height: 0 }, + tab, + tab.owner + ); } } catch (e) { console.error(e); diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index 323d31223..20eb67afc 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -1494,94 +1494,97 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { const canDrop = this._canDrop; this._maybeRemoveFakeBrowser(false); this._canDrop = false; + if (!canDrop) { return false; } - const dropTarget = document.elementFromPoint(event.clientX, event.clientY); - const browser = dropTarget?.closest('browser'); + window.requestAnimationFrame(() => { + const dropTarget = document.elementFromPoint(event.clientX, event.clientY); + const browser = dropTarget?.closest('browser'); - gBrowser.selectedTab = this._draggingTab; - this._draggingTab = null; + if (!browser) { + return false; + } - if (!browser) { - return false; - } + gBrowser.selectedTab = this._draggingTab; + this._draggingTab = null; - const droppedOnTab = gBrowser.getTabForBrowser(browser); - if (droppedOnTab && droppedOnTab !== draggedTab) { - // Calculate which side of the target browser the drop occurred - // const browserRect = browser.getBoundingClientRect(); - // const hoverSide = this.calculateHoverSide(event.clientX, event.clientY, browserRect); - const hoverSide = 'right'; + const droppedOnTab = gBrowser.getTabForBrowser(browser); + if (droppedOnTab && droppedOnTab !== draggedTab) { + // Calculate which side of the target browser the drop occurred + // const browserRect = browser.getBoundingClientRect(); + // const hoverSide = this.calculateHoverSide(event.clientX, event.clientY, browserRect); + const hoverSide = 'right'; - if (droppedOnTab.splitView) { - // Add to existing split view - const groupIndex = this._data.findIndex((group) => group.tabs.includes(droppedOnTab)); - const group = this._data[groupIndex]; + if (droppedOnTab.splitView) { + // Add to existing split view + const groupIndex = this._data.findIndex((group) => group.tabs.includes(droppedOnTab)); + const group = this._data[groupIndex]; - if (!group.tabs.includes(draggedTab) && group.tabs.length < this.MAX_TABS) { - // First move the tab to the split view group - let splitGroup = droppedOnTab.group; - if (splitGroup && (!draggedTab.group || draggedTab.group !== splitGroup)) { - this._moveTabsToContainer([draggedTab], droppedOnTab); - gBrowser.moveTabToGroup(draggedTab, splitGroup); - } + if (!group.tabs.includes(draggedTab) && group.tabs.length < this.MAX_TABS) { + // First move the tab to the split view group + let splitGroup = droppedOnTab.group; + if (splitGroup && (!draggedTab.group || draggedTab.group !== splitGroup)) { + this._moveTabsToContainer([draggedTab], droppedOnTab); + gBrowser.moveTabToGroup(draggedTab, splitGroup); + } - const droppedOnSplitNode = this.getSplitNodeFromTab(droppedOnTab); - const parentNode = droppedOnSplitNode.parent; + const droppedOnSplitNode = this.getSplitNodeFromTab(droppedOnTab); + const parentNode = droppedOnSplitNode.parent; - // Then add the tab to the split view - group.tabs.push(draggedTab); + // Then add the tab to the split view + group.tabs.push(draggedTab); - // If dropping on a side, create a new split in that direction - if (hoverSide !== 'center') { - const splitDirection = hoverSide === 'left' || hoverSide === 'right' ? 'row' : 'column'; - if (parentNode.direction !== splitDirection) { - this.splitIntoNode(droppedOnSplitNode, new SplitLeafNode(draggedTab, 50), hoverSide, 0.5); + // If dropping on a side, create a new split in that direction + if (hoverSide !== 'center') { + const splitDirection = hoverSide === 'left' || hoverSide === 'right' ? 'row' : 'column'; + if (parentNode.direction !== splitDirection) { + this.splitIntoNode(droppedOnSplitNode, new SplitLeafNode(draggedTab, 50), hoverSide, 0.5); + } else { + this.addTabToSplit(draggedTab, parentNode); + } } else { - this.addTabToSplit(draggedTab, parentNode); + this.addTabToSplit(draggedTab, group.layoutTree); } - } else { - this.addTabToSplit(draggedTab, group.layoutTree); + + this.activateSplitView(group, true); } + } else { + // Create new split view with layout based on drop position + let gridType = 'vsep'; + //switch (hoverSide) { + // case 'left': + // case 'right': + // gridType = 'vsep'; + // break; + // case 'top': + // case 'bottom': + // gridType = 'hsep'; + // break; + // default: + // gridType = 'grid'; + //} - this.activateSplitView(group, true); - } - } else { - // Create new split view with layout based on drop position - let gridType = 'vsep'; - //switch (hoverSide) { - // case 'left': - // case 'right': - // gridType = 'vsep'; - // break; - // case 'top': - // case 'bottom': - // gridType = 'hsep'; - // break; - // default: - // gridType = 'grid'; - //} - - // Put tabs always as if it was dropped from the left - this.splitTabs([draggedTab, droppedOnTab], gridType, 1); - if (draggedTab.linkedBrowser) { - gZenUIManager.motion.animate( - draggedTab.linkedBrowser.closest('.browserSidebarContainer'), - { - scale: [0.98, 1], - }, - { - type: 'spring', - bounce: 0.5, - duration: 0.5, - delay: 0.1, - } - ); + // Put tabs always as if it was dropped from the left + this.splitTabs([draggedTab, droppedOnTab], gridType, 1); + if (draggedTab.linkedBrowser) { + gZenUIManager.motion.animate( + draggedTab.linkedBrowser.closest('.browserSidebarContainer'), + { + scale: [0.98, 1], + }, + { + type: 'spring', + bounce: 0.5, + duration: 0.5, + delay: 0.1, + } + ); + } } } - } + }); return true; } From cc8a5cf3678bc8e73b8c8df966e9aab14f3d4411 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Tue, 4 Mar 2025 19:20:12 +0100 Subject: [PATCH 021/127] Update Firefox version to 136.0 in README and surfer.json; modify ToolbarContextMenu context menu items --- README.md | 2 +- .../content/main-popupset-inc-xhtml.patch | 18 +++++++++++++-- .../ToolbarContextMenu-sys-mjs.patch | 22 +++++++++++++++++++ surfer.json | 2 +- 4 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 src/browser/components/customizableui/ToolbarContextMenu-sys-mjs.patch diff --git a/README.md b/README.md index d42420977..6c0f170f0 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ ## 🖥️ Compatibility -Zen is currently built using Firefox version `135.0.1`! 🚀 +Zen is currently built using Firefox version `136.0`! 🚀 - [`Zen Twilight`](https://zen-browser.app/download?twilight) - Is currently built using Firefox version `RC 136.0`! - Check out the latest [release notes](https://zen-browser.app/release-notes)! diff --git a/src/browser/base/content/main-popupset-inc-xhtml.patch b/src/browser/base/content/main-popupset-inc-xhtml.patch index a49f1bef7..072fa90a1 100644 --- a/src/browser/base/content/main-popupset-inc-xhtml.patch +++ b/src/browser/base/content/main-popupset-inc-xhtml.patch @@ -1,5 +1,5 @@ diff --git a/browser/base/content/main-popupset.inc.xhtml b/browser/base/content/main-popupset.inc.xhtml -index 959c523b21c642f29353b9de37b3ce6b5505b01b..0d151ad345dde47467432196ed76f4320b4b92cc 100644 +index 959c523b21c642f29353b9de37b3ce6b5505b01b..4cd26ea85ad4905bade71dcd470b8678079787bd 100644 --- a/browser/base/content/main-popupset.inc.xhtml +++ b/browser/base/content/main-popupset.inc.xhtml @@ -206,6 +206,10 @@ @@ -21,7 +21,21 @@ index 959c523b21c642f29353b9de37b3ce6b5505b01b..0d151ad345dde47467432196ed76f432 -@@ -565,6 +570,8 @@ +@@ -426,11 +431,13 @@ + observes="cmd_CustomizeToolbars" + class="viewCustomizeToolbar" + data-lazy-l10n-id="toolbar-context-menu-view-customize-toolbar-2"/> ++#if 0 + + + ++#endif + + Toolbars menu doesn't have the moveToPanel or removeFromToolbar items. + if (!moveToPanel || !removeFromToolbar) { diff --git a/surfer.json b/surfer.json index 92291b134..37a48a0f3 100644 --- a/surfer.json +++ b/surfer.json @@ -5,7 +5,7 @@ "binaryName": "zen", "version": { "product": "firefox", - "version": "135.0.1", + "version": "136.0", "candidate": "136.0" }, "buildOptions": { From 452c19a7ea8ca526688dbbb0636c2fb7358bfdd0 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Tue, 4 Mar 2025 20:23:21 +0100 Subject: [PATCH 022/127] Refactor ZenViewSplitter to improve drag-and-drop functionality and enhance split view behavior --- src/browser/base/content/ZenUIManager.mjs | 1 + .../base/zen-components/ZenCompactMode.mjs | 3 - .../base/zen-components/ZenViewSplitter.mjs | 180 +++++++++--------- 3 files changed, 94 insertions(+), 90 deletions(-) diff --git a/src/browser/base/content/ZenUIManager.mjs b/src/browser/base/content/ZenUIManager.mjs index 03cd8afbe..9673974a0 100644 --- a/src/browser/base/content/ZenUIManager.mjs +++ b/src/browser/base/content/ZenUIManager.mjs @@ -62,6 +62,7 @@ var gZenUIManager = { } tabs.style.removeProperty('flex'); tabs.style.maxHeight = height + 'px'; + gZenVerticalTabsManager.actualWindowButtons.removeAttribute('zen-has-hover'); }, get tabsWrapper() { diff --git a/src/browser/base/zen-components/ZenCompactMode.mjs b/src/browser/base/zen-components/ZenCompactMode.mjs index 94f86472e..32c75edb9 100644 --- a/src/browser/base/zen-components/ZenCompactMode.mjs +++ b/src/browser/base/zen-components/ZenCompactMode.mjs @@ -312,9 +312,6 @@ var gZenCompactModeManager = { { element: gZenVerticalTabsManager.actualWindowButtons, }, - { - element: gZenVerticalTabsManager.actualWindowButtons, - }, ]; }, diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index 20eb67afc..b78528b9f 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -90,8 +90,8 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { // Add drag over listener to the browser view const tabBox = document.getElementById('tabbrowser-tabbox'); - tabBox.addEventListener('dragenter', this.onBrowserDragOverToSplit.bind(this)); - tabBox.addEventListener('dragleave', this.onBrowserDragEndToSplit.bind(this)); + tabBox.addEventListener('dragover', this.onBrowserDragOverToSplit.bind(this)); + this.onBrowserDragEndToSplit = this.onBrowserDragEndToSplit.bind(this); } insertIntoContextMenu() { @@ -198,7 +198,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { // only show if we are 1/4 of the way to the edge const panelsRect = gBrowser.tabbox.getBoundingClientRect(); const panelsWidth = panelsRect.width; - if (event.clientX > (panelsWidth / 4) * 3) { + if (event.clientX > panelsWidth / 4 || event.clientX < panelsRect.left + 20) { return; } const oldTab = this._lastOpenedTab; @@ -211,12 +211,12 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { const panelsWidth = gBrowser.tabbox.getBoundingClientRect().width; const halfWidth = panelsWidth / 2; this.fakeBrowser = document.createXULElement('vbox'); + this.fakeBrowser.addEventListener('dragleave', this.onBrowserDragEndToSplit); const padding = Services.prefs.getIntPref('zen.theme.content-element-separation', 0); this.fakeBrowser.setAttribute('flex', '1'); this.fakeBrowser.id = 'zen-split-view-fake-browser'; gBrowser.tabbox.appendChild(this.fakeBrowser); this.fakeBrowser.style.setProperty('--zen-split-view-fake-icon', `url(${draggedTab.getAttribute('image')})`); - draggedTab._visuallySelected = true; Promise.all([ gZenUIManager.motion.animate( gBrowser.tabbox, @@ -239,7 +239,9 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { easing: 'ease-out', } ), - ]).then(() => {}); + ]).then(() => { + draggedTab._visuallySelected = true; + }); }, 100); } @@ -263,10 +265,6 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { if (!this.fakeBrowser) { return; } - // if we are still in that 1/4 of the way to the edge then we should not hide the fake browser - if (event.clientX < (panelsWidth / 4) * 3 && event.clientX > panelsRect.left) { - return; - } this.fakeBrowser.classList.add('fade-out'); gBrowser.selectedTab = this._draggingTab; this._draggingTab = null; @@ -365,14 +363,13 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { afterRearangeAction() { document.getElementById('zenSplitViewModifier').hidePopup(); - ConfirmationHint.show(document.getElementById('zen-split-views-box'), 'zen-split-view-modifier-enabled-toast', { + gZenUIManager.showToast('zen-split-view-modifier-enabled-toast', { descriptionId: 'zen-split-view-modifier-enabled-toast-description', - showDescription: true, }); } afterRearangeRemove() { - ConfirmationHint.show(document.getElementById('zen-split-views-box'), 'zen-split-view-modifier-disabled-toast'); + gZenUIManager.showToast('zen-split-view-modifier-disabled-toast'); } toggleWrapperDisplay(value) { @@ -1434,7 +1431,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { return; } const tabs = gBrowser.visibleTabs; - if (tabs.length < 2) { + if (tabs.length < 2 || this.currentView >= 0) { return; } let nextTabIndex = tabs.indexOf(gBrowser.selectedTab) + 1; @@ -1464,6 +1461,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { const tab = gBrowser.getTabForBrowser(browser); if (tab) { const groupIndex = this._data.findIndex((group) => group.tabs.includes(tab)); + this.deactivateCurrentSplitView(); if (groupIndex >= 0) { this.removeTabFromGroup(tab, groupIndex, true); } @@ -1477,6 +1475,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { delete this._hasAnimated; this.fakeBrowser.remove(); this.fakeBrowser = null; + this._draggingTab._visuallySelected = false; if (select) { gBrowser.selectedTab = this._draggingTab; this._draggingTab = null; @@ -1492,99 +1491,106 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { */ moveTabToSplitView(event, draggedTab) { const canDrop = this._canDrop; - this._maybeRemoveFakeBrowser(false); this._canDrop = false; - if (!canDrop) { + if (!canDrop || !this.fakeBrowser) { + this._maybeRemoveFakeBrowser(false); return false; } - window.requestAnimationFrame(() => { - const dropTarget = document.elementFromPoint(event.clientX, event.clientY); - const browser = dropTarget?.closest('browser'); + const containerRect = this.fakeBrowser.getBoundingClientRect(); + const dropTarget = document.elementFromPoint((containerRect.left + containerRect.width) * 1.5, event.clientY); + const browser = dropTarget?.closest('browser'); - if (!browser) { - return false; - } + if (!browser) { + this._maybeRemoveFakeBrowser(false); + return false; + } - gBrowser.selectedTab = this._draggingTab; - this._draggingTab = null; + gBrowser.selectedTab = this._draggingTab; + this._draggingTab = null; + const browserContainer = draggedTab.linkedBrowser?.closest('.browserSidebarContainer'); + if (browserContainer) { + browserContainer.style.opacity = '0'; + } - const droppedOnTab = gBrowser.getTabForBrowser(browser); - if (droppedOnTab && droppedOnTab !== draggedTab) { - // Calculate which side of the target browser the drop occurred - // const browserRect = browser.getBoundingClientRect(); - // const hoverSide = this.calculateHoverSide(event.clientX, event.clientY, browserRect); - const hoverSide = 'right'; + const droppedOnTab = gBrowser.getTabForBrowser(browser); + if (droppedOnTab && droppedOnTab !== draggedTab) { + // Calculate which side of the target browser the drop occurred + // const browserRect = browser.getBoundingClientRect(); + // const hoverSide = this.calculateHoverSide(event.clientX, event.clientY, browserRect); + const hoverSide = 'right'; - if (droppedOnTab.splitView) { - // Add to existing split view - const groupIndex = this._data.findIndex((group) => group.tabs.includes(droppedOnTab)); - const group = this._data[groupIndex]; + if (droppedOnTab.splitView) { + // Add to existing split view + const groupIndex = this._data.findIndex((group) => group.tabs.includes(droppedOnTab)); + const group = this._data[groupIndex]; - if (!group.tabs.includes(draggedTab) && group.tabs.length < this.MAX_TABS) { - // First move the tab to the split view group - let splitGroup = droppedOnTab.group; - if (splitGroup && (!draggedTab.group || draggedTab.group !== splitGroup)) { - this._moveTabsToContainer([draggedTab], droppedOnTab); - gBrowser.moveTabToGroup(draggedTab, splitGroup); - } + if (!group.tabs.includes(draggedTab) && group.tabs.length < this.MAX_TABS) { + // First move the tab to the split view group + let splitGroup = droppedOnTab.group; + if (splitGroup && (!draggedTab.group || draggedTab.group !== splitGroup)) { + this._moveTabsToContainer([draggedTab], droppedOnTab); + gBrowser.moveTabToGroup(draggedTab, splitGroup); + } - const droppedOnSplitNode = this.getSplitNodeFromTab(droppedOnTab); - const parentNode = droppedOnSplitNode.parent; + const droppedOnSplitNode = this.getSplitNodeFromTab(droppedOnTab); + const parentNode = droppedOnSplitNode.parent; - // Then add the tab to the split view - group.tabs.push(draggedTab); + // Then add the tab to the split view + group.tabs.push(draggedTab); - // If dropping on a side, create a new split in that direction - if (hoverSide !== 'center') { - const splitDirection = hoverSide === 'left' || hoverSide === 'right' ? 'row' : 'column'; - if (parentNode.direction !== splitDirection) { - this.splitIntoNode(droppedOnSplitNode, new SplitLeafNode(draggedTab, 50), hoverSide, 0.5); - } else { - this.addTabToSplit(draggedTab, parentNode); - } + // If dropping on a side, create a new split in that direction + if (hoverSide !== 'center') { + const splitDirection = hoverSide === 'left' || hoverSide === 'right' ? 'row' : 'column'; + if (parentNode.direction !== splitDirection) { + this.splitIntoNode(droppedOnSplitNode, new SplitLeafNode(draggedTab, 50), hoverSide, 0.5); } else { - this.addTabToSplit(draggedTab, group.layoutTree); + this.addTabToSplit(draggedTab, parentNode); } - - this.activateSplitView(group, true); + } else { + this.addTabToSplit(draggedTab, group.layoutTree); } - } else { - // Create new split view with layout based on drop position - let gridType = 'vsep'; - //switch (hoverSide) { - // case 'left': - // case 'right': - // gridType = 'vsep'; - // break; - // case 'top': - // case 'bottom': - // gridType = 'hsep'; - // break; - // default: - // gridType = 'grid'; - //} - // Put tabs always as if it was dropped from the left - this.splitTabs([draggedTab, droppedOnTab], gridType, 1); - if (draggedTab.linkedBrowser) { - gZenUIManager.motion.animate( - draggedTab.linkedBrowser.closest('.browserSidebarContainer'), - { - scale: [0.98, 1], - }, - { - type: 'spring', - bounce: 0.5, - duration: 0.5, - delay: 0.1, - } - ); - } + this.activateSplitView(group, true); } + } else { + // Create new split view with layout based on drop position + let gridType = 'vsep'; + //switch (hoverSide) { + // case 'left': + // case 'right': + // gridType = 'vsep'; + // break; + // case 'top': + // case 'bottom': + // gridType = 'hsep'; + // break; + // default: + // gridType = 'grid'; + //} + + // Put tabs always as if it was dropped from the left + this.splitTabs([draggedTab, droppedOnTab], gridType, 1); } - }); + } + this._maybeRemoveFakeBrowser(false); + + if (browserContainer) { + gZenUIManager.motion.animate( + browserContainer, + { + scale: [0.97, 1], + opacity: [0, 1], + }, + { + type: 'spring', + bounce: 0.4, + duration: 0.2, + delay: 0.1, + } + ); + } return true; } From 1c49cffc66e5768d65ff67d5eeb478aa0beea494 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Tue, 4 Mar 2025 20:26:46 +0100 Subject: [PATCH 023/127] Update vertical-tabs.css to set a fixed minimum width for tab columns --- src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css index b2f7e206b..5a3aeb4bf 100644 --- a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css +++ b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css @@ -1050,7 +1050,7 @@ overflow: hidden; transition: max-height 0.3s ease-out; opacity: 1; - grid-template-columns: repeat(auto-fit, minmax(var(--tab-pinned-min-width-expanded), auto)); + grid-template-columns: repeat(auto-fit, minmax(48px, auto)); overflow: hidden; scrollbar-width: thin; display: grid; From c78cafe6051129e75c9369eb96cbfdffe3c9ee83 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Tue, 4 Mar 2025 20:46:57 +0100 Subject: [PATCH 024/127] Refactor CSS styles for zen components and update tab icon handling in ZenPinnedTabManager --- src/browser/base/content/zen-styles/zen-decks.css | 1 - src/browser/base/content/zen-styles/zen-sidebar-panels.css | 2 +- .../base/content/zen-styles/zen-tabs/vertical-tabs.css | 2 +- src/browser/base/content/zen-styles/zen-workspaces.css | 1 + src/browser/base/zen-components/ZenPinnedTabManager.mjs | 5 ++++- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-decks.css b/src/browser/base/content/zen-styles/zen-decks.css index 79200caec..7ba7975f5 100644 --- a/src/browser/base/content/zen-styles/zen-decks.css +++ b/src/browser/base/content/zen-styles/zen-decks.css @@ -34,7 +34,6 @@ margin-left: 0 !important; position: absolute !important; overflow: hidden; - transition: inset 0.1s; } #tabbrowser-tabpanels[zen-split-view='true']:not([zen-split-resizing]) > [zen-split-anim='true'] { diff --git a/src/browser/base/content/zen-styles/zen-sidebar-panels.css b/src/browser/base/content/zen-styles/zen-sidebar-panels.css index a7cb968b5..d82053403 100644 --- a/src/browser/base/content/zen-styles/zen-sidebar-panels.css +++ b/src/browser/base/content/zen-styles/zen-sidebar-panels.css @@ -121,7 +121,7 @@ &::before { height: 50px; - width: 4px; + width: 2px; background: var(--button-primary-bgcolor); border-radius: 2px; content: ''; diff --git a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css index 5a3aeb4bf..a28b4fdab 100644 --- a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css +++ b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css @@ -264,7 +264,7 @@ display: none; } - &:active { + #tabbrowser-tabs:not([movingtab]) &:active { scale: var(--zen-active-tab-scale); } diff --git a/src/browser/base/content/zen-styles/zen-workspaces.css b/src/browser/base/content/zen-styles/zen-workspaces.css index 9a13ac4da..ded029357 100644 --- a/src/browser/base/content/zen-styles/zen-workspaces.css +++ b/src/browser/base/content/zen-styles/zen-workspaces.css @@ -499,6 +499,7 @@ overflow: hidden; text-overflow: ellipsis; pointer-events: none; + font-size: small; } } diff --git a/src/browser/base/zen-components/ZenPinnedTabManager.mjs b/src/browser/base/zen-components/ZenPinnedTabManager.mjs index c8ac86c2d..4f18c23d9 100644 --- a/src/browser/base/zen-components/ZenPinnedTabManager.mjs +++ b/src/browser/base/zen-components/ZenPinnedTabManager.mjs @@ -84,7 +84,10 @@ onTabIconChanged(tab, url = null) { const iconUrl = url ?? tab.iconImage.src; if (tab.hasAttribute('zen-essential')) { - tab.querySelector('.tab-background').style.setProperty('--zen-tab-icon', `url(${iconUrl})`); + const pin = this._pinsCache.find((pin) => pin.uuid === tab.getAttribute('zen-pin-id')); + if (pin) { + tab.querySelector('.tab-background').style.setProperty('--zen-tab-icon', `url(${pin.iconUrl})`); + } } // TODO: work on this //if (tab.hasAttribute('zen-pinned-changed') || !this._pinsCache) { From 1ba809825db62e347a7e642169be549730759dad Mon Sep 17 00:00:00 2001 From: "mr. m" <91018726+mauro-balades@users.noreply.github.com> Date: Tue, 4 Mar 2025 21:00:17 +0100 Subject: [PATCH 025/127] Fixed fully opening glance appearing on random places if container specific essentials are on Signed-off-by: mr. m <91018726+mauro-balades@users.noreply.github.com> --- src/browser/base/zen-components/ZenGlanceManager.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/base/zen-components/ZenGlanceManager.mjs b/src/browser/base/zen-components/ZenGlanceManager.mjs index 578eb8183..f8368dbed 100644 --- a/src/browser/base/zen-components/ZenGlanceManager.mjs +++ b/src/browser/base/zen-components/ZenGlanceManager.mjs @@ -70,7 +70,7 @@ } getTabPosition(tab) { - return Math.max(gBrowser._numVisiblePinTabs, tab._tPos); + return Math.max(gBrowser.pinnedTabCount, tab._tPos); } createBrowserElement(url, currentTab, existingTab = null) { From 9b07fd528bd388bf0562fd842bc8417ee35b7a42 Mon Sep 17 00:00:00 2001 From: Slowlife01 Date: Mon, 3 Mar 2025 11:45:59 +0700 Subject: [PATCH 026/127] Fix: External link not opening in default container --- src/browser/base/zen-components/ZenWorkspaces.mjs | 2 +- src/browser/components/tabbrowser/content/tabbrowser-js.patch | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/browser/base/zen-components/ZenWorkspaces.mjs b/src/browser/base/zen-components/ZenWorkspaces.mjs index 3d7a7a530..7e8ca9969 100644 --- a/src/browser/base/zen-components/ZenWorkspaces.mjs +++ b/src/browser/base/zen-components/ZenWorkspaces.mjs @@ -2232,7 +2232,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { const activeWorkspace = this.getActiveWorkspaceFromCache(); const activeWorkspaceUserContextId = activeWorkspace?.containerTabId; - if (typeof userContextId !== 'undefined' && userContextId !== activeWorkspaceUserContextId) { + if (fromExternal !== true && typeof userContextId !== 'undefined' && userContextId !== activeWorkspaceUserContextId) { return [userContextId, false, undefined]; } return [activeWorkspaceUserContextId, true, undefined]; diff --git a/src/browser/components/tabbrowser/content/tabbrowser-js.patch b/src/browser/components/tabbrowser/content/tabbrowser-js.patch index 90b4ac070..13b4f9136 100644 --- a/src/browser/components/tabbrowser/content/tabbrowser-js.patch +++ b/src/browser/components/tabbrowser/content/tabbrowser-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js -index 628aa6596627c85efe361fc1ece8fd58f7ee653e..372a783210c5829533eb8c2b3ca32a370be5f820 100644 +index 628aa6596627c85efe361fc1ece8fd58f7ee653e..a05cbeeb96d18519c2a090bdcd8df8f3e42d020f 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js @@ -412,11 +412,50 @@ @@ -197,7 +197,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..372a783210c5829533eb8c2b3ca32a37 + let hasZenDefaultUserContextId = false; + let zenForcedWorkspaceId = undefined; -+ if (typeof ZenWorkspaces !== "undefined") { ++ if (typeof ZenWorkspaces !== "undefined" && !_forZenEmptyTab) { + [userContextId, hasZenDefaultUserContextId, zenForcedWorkspaceId] = ZenWorkspaces.getContextIdIfNeeded(userContextId, fromExternal, allowInheritPrincipal); + } + From c61112bc6d27b74f5866f5a0710491ad7b8eb551 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Wed, 5 Mar 2025 12:14:03 +0100 Subject: [PATCH 027/127] Fixed common issues with split views not being properly registered --- src/browser/app/profile/zen-browser.js | 2 +- .../base/zen-components/ZenViewSplitter.mjs | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/browser/app/profile/zen-browser.js b/src/browser/app/profile/zen-browser.js index 7e038cf30..bff897d67 100644 --- a/src/browser/app/profile/zen-browser.js +++ b/src/browser/app/profile/zen-browser.js @@ -81,7 +81,7 @@ pref('zen.tabs.vertical', true); pref('zen.tabs.vertical.right-side', false); pref('zen.tabs.rename-tabs', true); pref('zen.theme.accent-color', "#ffb787"); -pref('zen.theme.content-element-separation', 6); // In pixels +pref('zen.theme.content-element-separation', 10); // In pixels pref('zen.theme.gradient', true); pref('zen.theme.gradient.show-custom-colors', false); pref('zen.theme.essentials-favicon-bg', true); diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index b78528b9f..6b313abf8 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -198,7 +198,12 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { // only show if we are 1/4 of the way to the edge const panelsRect = gBrowser.tabbox.getBoundingClientRect(); const panelsWidth = panelsRect.width; - if (event.clientX > panelsWidth / 4 || event.clientX < panelsRect.left + 20) { + if ( + event.clientX > panelsWidth / 2 || + event.clientX < panelsRect.left + 10 || + event.clientY < panelsRect.top + 10 || + event.clientY > panelsRect.bottom - 10 + ) { return; } const oldTab = this._lastOpenedTab; @@ -231,8 +236,8 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { gZenUIManager.motion.animate( this.fakeBrowser, { - width: [0, `${halfWidth - padding * 2}px`], - marginLeft: [0, `${-(halfWidth - padding)}px`], + width: [0, `${halfWidth - padding}px`], + marginLeft: [0, `${-halfWidth}px`], }, { duration: 0.15, @@ -250,7 +255,11 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { return; } const panelsRect = gBrowser.tabbox.getBoundingClientRect(); - if (event.target.closest('#tabbrowser-tabbox') && event.target != this.fakeBrowser) { + const fakeBrowserRect = this.fakeBrowser && this.fakeBrowser.getBoundingClientRect(); + if ( + (event.target.closest('#tabbrowser-tabbox') && event.target != this.fakeBrowser) || + (fakeBrowserRect && event.clientX > fakeBrowserRect.left && event.clientX < fakeBrowserRect.left + fakeBrowserRect.width) + ) { return; } if (this._showSplitViewTimeout) { From ab127daa354cd5d9e296f40899137a8a6c7f1a63 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Wed, 5 Mar 2025 12:34:42 +0100 Subject: [PATCH 028/127] Small fixes to the welcome page --- .../base/content/zen-styles/zen-tabs/vertical-tabs.css | 2 +- src/browser/base/content/zen-styles/zen-welcome.css | 9 +++++++-- src/browser/base/zen-components/ZenWelcome.mjs | 7 ++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css index a28b4fdab..84ff008d0 100644 --- a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css +++ b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css @@ -109,7 +109,7 @@ } & #zen-sidebar-top-buttons { - margin: 4px 0; + margin: var(--zen-element-separation) 0 var(--zen-toolbox-padding) 0; } & #PanelUI-menu-button { diff --git a/src/browser/base/content/zen-styles/zen-welcome.css b/src/browser/base/content/zen-styles/zen-welcome.css index 69020b6f4..f67fa8eb2 100644 --- a/src/browser/base/content/zen-styles/zen-welcome.css +++ b/src/browser/base/content/zen-styles/zen-welcome.css @@ -58,6 +58,7 @@ width: 60%; height: 60%; box-shadow: var(--zen-big-shadow); + overflow: hidden; /* Small screens */ @media (max-width: 1400px) { @@ -96,6 +97,10 @@ background-repeat: no-repeat; background-position: center; } + + &[animate-heart] { + overflow: hidden; + } } #zen-welcome-page-sidebar-buttons { @@ -129,6 +134,7 @@ #zen-welcome-page-content { background: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.1)); width: 60%; + max-width: 80rem; height: 100%; position: relative; overflow: hidden; @@ -205,7 +211,7 @@ #zen-welcome-initial-essentials-browser-sidebar-essentials { display: grid; grid-template-columns: repeat(3, 1fr); - gap: 0.8rem; + gap: 0.4rem 1.2rem; visibility: visible; & * { @@ -247,7 +253,6 @@ transform: scale(1.04); & .tab-background { - --zen-essential-bg-margin: 3px; box-shadow: var(--zen-big-shadow); } } diff --git a/src/browser/base/zen-components/ZenWelcome.mjs b/src/browser/base/zen-components/ZenWelcome.mjs index 730296af6..a7a285f56 100644 --- a/src/browser/base/zen-components/ZenWelcome.mjs +++ b/src/browser/base/zen-components/ZenWelcome.mjs @@ -226,6 +226,7 @@ const sidebar = document.getElementById('zen-welcome-page-sidebar'); sidebar.style.width = '100%'; sidebar.appendChild(heart); + sidebar.setAttribute('animate-heart', 'true'); await animate( '#zen-welcome-heart', { opacity: [0, 1, 1, 1, 0], scale: [0.5, 1, 1.2, 1, 1.2] }, @@ -349,12 +350,12 @@ - + - + @@ -364,7 +365,7 @@ - + From 188a6ea8015a951ffc3fd3ac1051101407059614 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Wed, 5 Mar 2025 12:51:44 +0100 Subject: [PATCH 029/127] Small fixes to the URL bar --- src/browser/app/profile/zen-browser.js | 2 +- .../themes/shared/urlbar-searchbar-css.patch | 11 ++++++++++- src/browser/themes/shared/urlbarView-css.patch | 13 +++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 src/browser/themes/shared/urlbarView-css.patch diff --git a/src/browser/app/profile/zen-browser.js b/src/browser/app/profile/zen-browser.js index bff897d67..62aa95df0 100644 --- a/src/browser/app/profile/zen-browser.js +++ b/src/browser/app/profile/zen-browser.js @@ -379,7 +379,7 @@ pref('widget.macos.titlebar-blend-mode.behind-window', true); // 5. toolTip // 6. headerView // 7. underlay -pref('zen.widget.macos.window-material', 1); +pref('zen.widget.macos.window-material', 3); #endif // Urlbar and autocomplete diff --git a/src/browser/themes/shared/urlbar-searchbar-css.patch b/src/browser/themes/shared/urlbar-searchbar-css.patch index e270338e9..259fe7eaf 100644 --- a/src/browser/themes/shared/urlbar-searchbar-css.patch +++ b/src/browser/themes/shared/urlbar-searchbar-css.patch @@ -1,7 +1,16 @@ diff --git a/browser/themes/shared/urlbar-searchbar.css b/browser/themes/shared/urlbar-searchbar.css -index 45aa61f93d354da432eceb1c276466609a6910d0..6585158b855af19689e86ef6a833f63736ec225c 100644 +index 574f83af7fa49ddcdff6711ca8b1d3bed1a35e0c..c2e8cb8b37438176db07a47e1e975ae1aea42252 100644 --- a/browser/themes/shared/urlbar-searchbar.css +++ b/browser/themes/shared/urlbar-searchbar.css +@@ -5,7 +5,7 @@ + @namespace html url("http://www.w3.org/1999/xhtml"); + + :root { +- --urlbar-container-padding: 1px; ++ --urlbar-container-padding: 4px; + --urlbar-margin-inline: 5px; + --urlbar-padding-block: 4px; + } @@ -291,7 +291,9 @@ } diff --git a/src/browser/themes/shared/urlbarView-css.patch b/src/browser/themes/shared/urlbarView-css.patch new file mode 100644 index 000000000..2e7241a17 --- /dev/null +++ b/src/browser/themes/shared/urlbarView-css.patch @@ -0,0 +1,13 @@ +diff --git a/browser/themes/shared/urlbarView.css b/browser/themes/shared/urlbarView.css +index 1c654e053ca8a014d7c2a9fc076cf15afba9c903..f2f63809d0a36db2774755db2b782f41a9bbe82b 100644 +--- a/browser/themes/shared/urlbarView.css ++++ b/browser/themes/shared/urlbarView.css +@@ -20,7 +20,7 @@ + + --urlbarView-small-font-size: 0.85em; + +- --urlbarView-results-padding: 4px; ++ --urlbarView-results-padding: 8px; + --urlbarView-row-gutter: 2px; + --urlbarView-item-inline-padding: var(--urlbar-icon-padding); + --urlbarView-item-block-padding: 6px; From 55275b23aafcf4b200e40b607e240f3dd0d27cac Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Wed, 5 Mar 2025 13:05:39 +0100 Subject: [PATCH 030/127] Small adjustments to compact mode and the URL bar background --- .../base/content/zen-styles/zen-compact-mode.css | 4 ++++ .../base/content/zen-styles/zen-tabs/vertical-tabs.css | 2 +- src/browser/base/content/zen-styles/zen-urlbar.css | 10 ++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/browser/base/content/zen-styles/zen-compact-mode.css b/src/browser/base/content/zen-styles/zen-compact-mode.css index dc7e849b0..1d890b0af 100644 --- a/src/browser/base/content/zen-styles/zen-compact-mode.css +++ b/src/browser/base/content/zen-styles/zen-compact-mode.css @@ -57,6 +57,10 @@ top: calc(var(--zen-element-separation) / 2); height: calc(100% - var(--zen-element-separation)); } + + & #zen-sidebar-top-buttons { + margin: 0 0 calc(var(--zen-toolbox-padding) / 2) 0; + } } &:not([zen-right-side='true']) #nav-bar { diff --git a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css index 84ff008d0..5e272a97d 100644 --- a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css +++ b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css @@ -109,7 +109,7 @@ } & #zen-sidebar-top-buttons { - margin: var(--zen-element-separation) 0 var(--zen-toolbox-padding) 0; + margin: var(--zen-element-separation) 0 calc(var(--zen-toolbox-padding) / 2) 0; } & #PanelUI-menu-button { diff --git a/src/browser/base/content/zen-styles/zen-urlbar.css b/src/browser/base/content/zen-styles/zen-urlbar.css index 92680874b..e7d1d2fd3 100644 --- a/src/browser/base/content/zen-styles/zen-urlbar.css +++ b/src/browser/base/content/zen-styles/zen-urlbar.css @@ -44,6 +44,16 @@ outline-color: none !important; } +#urlbar:not([breakout-extend='true']) { + & #urlbar-background { + transition: background-color 0.15s ease; + } + + &:hover #urlbar-background { + background-color: light-dark(rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0.2)) !important; + } +} + #identity-box.chromeUI:not([pageproxystate='invalid']) { & #identity-icon-box { background: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.1)) !important; From 996f04296162d9a5f1209722c137de3fa6bfddf1 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Wed, 5 Mar 2025 15:08:10 +0100 Subject: [PATCH 031/127] Increased border radius for compact mode --- src/browser/base/content/zen-styles/zen-compact-mode.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/base/content/zen-styles/zen-compact-mode.css b/src/browser/base/content/zen-styles/zen-compact-mode.css index 1d890b0af..bb0f98601 100644 --- a/src/browser/base/content/zen-styles/zen-compact-mode.css +++ b/src/browser/base/content/zen-styles/zen-compact-mode.css @@ -98,7 +98,7 @@ #navigator-toolbox:not([animate='true']) #titlebar { box-shadow: var(--zen-big-shadow); - border-radius: var(--zen-native-inner-radius); + border-radius: calc(var(--zen-native-inner-radius) + var(--zen-element-separation) / 4); padding: var(--zen-toolbox-padding) !important; position: relative; background: var(--zen-dialog-background); From 03f6e6193573c8662c86474aee0ff2d8ab322af4 Mon Sep 17 00:00:00 2001 From: Slowlife01 Date: Wed, 5 Mar 2025 21:34:16 +0700 Subject: [PATCH 032/127] Feat: add drag event support for compact mode --- .../base/zen-components/ZenCompactMode.mjs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/browser/base/zen-components/ZenCompactMode.mjs b/src/browser/base/zen-components/ZenCompactMode.mjs index 32c75edb9..9d1309bf3 100644 --- a/src/browser/base/zen-components/ZenCompactMode.mjs +++ b/src/browser/base/zen-components/ZenCompactMode.mjs @@ -347,14 +347,13 @@ var gZenCompactModeManager = { addMouseActions() { for (let i = 0; i < this.hoverableElements.length; i++) { let target = this.hoverableElements[i].element; - target.addEventListener('mouseenter', (event) => { - if (!event.target.matches(':hover')) return; + const onEnter = (event) => { + if (event.type === 'mouseenter' && !event.target.matches(':hover')) return; this.clearFlashTimeout('has-hover' + target.id); window.requestAnimationFrame(() => target.setAttribute('zen-has-hover', 'true')); - }); + }; - target.addEventListener('mouseleave', (event) => { - // If on Mac, ignore mouseleave in the area of window buttons + const onLeave = (event) => { if (AppConstants.platform == 'macosx') { const buttonRect = gZenVerticalTabsManager.actualWindowButtons.getBoundingClientRect(); const MAC_WINDOW_BUTTONS_X_BORDER = buttonRect.width + buttonRect.x; @@ -379,7 +378,13 @@ var gZenCompactModeManager = { } else { this._removeHoverFrames[target.id] = window.requestAnimationFrame(() => target.removeAttribute('zen-has-hover')); } - }); + }; + + target.addEventListener('mouseenter', onEnter); + target.addEventListener('dragover', onEnter); + + target.addEventListener('mouseleave', onLeave); + target.addEventListener('dragleave', onLeave); } document.documentElement.addEventListener('mouseleave', (event) => { From ce2e492632c846200700d5649925bccac20f0f0b Mon Sep 17 00:00:00 2001 From: Samuel <36420837+Samueru-sama@users.noreply.github.com> Date: Wed, 5 Mar 2025 11:33:28 -0400 Subject: [PATCH 033/127] fix appimage not being able to set itself as default web browser Signed-off-by: Samuel <36420837+Samueru-sama@users.noreply.github.com> --- AppDir/AppRun | 1 + 1 file changed, 1 insertion(+) diff --git a/AppDir/AppRun b/AppDir/AppRun index dd148faf3..523d60514 100644 --- a/AppDir/AppRun +++ b/AppDir/AppRun @@ -9,6 +9,7 @@ DEFAULT_XDG_DATA_DIRS='./share/:/usr/share/gnome:/usr/local/share/:/usr/share/' export XDG_DATA_DIRS="${HERE}/usr/share/:${XDG_DATA_DIRS:-$DEFAULT_XDG_DATA_DIRS}" export PERLLIB="${HERE}/usr/share/perl5/:${HERE}/usr/lib/perl5/${PERLLIB:+:$PERLLIB}" export GSETTINGS_SCHEMA_DIR="${HERE}/usr/share/glib-2.0/schemas/${GSETTINGS_SCHEMA_DIR:+:$GSETTINGS_SCHEMA_DIR}" +export MOZ_APP_LAUNCHER="${APPIMAGE}" export QT_PLUGIN_PATH="${HERE}/usr/lib/qt4/plugins/:${HERE}/usr/lib/i386-linux-gnu/qt4/plugins/:${HERE}/usr/lib/x86_64-linux-gnu/qt4/plugins/:${HERE}/usr/lib32/qt4/plugins/:${HERE}/usr/lib64/qt4/plugins/:${HERE}/usr/lib/qt5/plugins/:${HERE}/usr/lib/i386-linux-gnu/qt5/plugins/:${HERE}/usr/lib/x86_64-linux-gnu/qt5/plugins/:${HERE}/usr/lib32/qt5/plugins/:${HERE}/usr/lib64/qt5/plugins/${QT_PLUGIN_PATH:+:$QT_PLUGIN_PATH}" EXEC=$(grep -e '^Exec=.*' "${HERE}"/*.desktop | head -n 1 | cut -d "=" -f 2 | cut -d " " -f 1) exec "${EXEC}" "$@" From 162e6abcc16a8cdff765e9c3e0e2666232684d01 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Wed, 5 Mar 2025 20:02:10 +0100 Subject: [PATCH 034/127] Enhance tab icon handling and improve event detection in ZenViewSplitter; update version numbers in surfer.json --- src/browser/base/zen-components/ZenPinnedTabManager.mjs | 2 +- src/browser/base/zen-components/ZenViewSplitter.mjs | 5 ++++- surfer.json | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/browser/base/zen-components/ZenPinnedTabManager.mjs b/src/browser/base/zen-components/ZenPinnedTabManager.mjs index 4f18c23d9..35f937ac2 100644 --- a/src/browser/base/zen-components/ZenPinnedTabManager.mjs +++ b/src/browser/base/zen-components/ZenPinnedTabManager.mjs @@ -83,7 +83,7 @@ onTabIconChanged(tab, url = null) { const iconUrl = url ?? tab.iconImage.src; - if (tab.hasAttribute('zen-essential')) { + if (tab.hasAttribute('zen-essential') && this._pinsCache) { const pin = this._pinsCache.find((pin) => pin.uuid === tab.getAttribute('zen-pin-id')); if (pin) { tab.querySelector('.tab-background').style.setProperty('--zen-tab-icon', `url(${pin.iconUrl})`); diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index 6b313abf8..8167cd6f1 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -258,7 +258,10 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { const fakeBrowserRect = this.fakeBrowser && this.fakeBrowser.getBoundingClientRect(); if ( (event.target.closest('#tabbrowser-tabbox') && event.target != this.fakeBrowser) || - (fakeBrowserRect && event.clientX > fakeBrowserRect.left && event.clientX < fakeBrowserRect.left + fakeBrowserRect.width) + (fakeBrowserRect && + event.clientX > fakeBrowserRect.left && + event.clientX < fakeBrowserRect.left + fakeBrowserRect.width) || + (event.clickX === 0 && event.clientY === 0) // It's equivalent to 0 if the event has been dropped ) { return; } diff --git a/surfer.json b/surfer.json index 37a48a0f3..9e1b56efb 100644 --- a/surfer.json +++ b/surfer.json @@ -19,7 +19,7 @@ "brandShortName": "Zen", "brandFullName": "Zen Browser", "release": { - "displayVersion": "1.8.2b", + "displayVersion": "1.9b", "github": { "repo": "zen-browser/desktop" }, @@ -39,7 +39,7 @@ "brandShortName": "Twilight", "brandFullName": "Zen Twilight", "release": { - "displayVersion": "1.8.2t", + "displayVersion": "1.9t", "github": { "repo": "zen-browser/desktop" } @@ -53,4 +53,4 @@ "licenseType": "MPL-2.0" }, "updateHostname": "updates.zen-browser.app" -} \ No newline at end of file +} From f0e2a68abf9609ba1c7b0492d4f12a9dde7727e8 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Wed, 5 Mar 2025 20:06:53 +0100 Subject: [PATCH 035/127] Refactor tab handling logic in ZenViewSplitter; ensure empty tab is last and remove fake browser when moving tabs --- .../tabbrowser/content/tabbrowser-js.patch | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/browser/components/tabbrowser/content/tabbrowser-js.patch b/src/browser/components/tabbrowser/content/tabbrowser-js.patch index 13b4f9136..95c664b4b 100644 --- a/src/browser/components/tabbrowser/content/tabbrowser-js.patch +++ b/src/browser/components/tabbrowser/content/tabbrowser-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js -index 628aa6596627c85efe361fc1ece8fd58f7ee653e..a05cbeeb96d18519c2a090bdcd8df8f3e42d020f 100644 +index 628aa6596627c85efe361fc1ece8fd58f7ee653e..1cd7343818d25e40d4a441f70307f7ce7ff98054 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js @@ -412,11 +412,50 @@ @@ -544,16 +544,17 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..a05cbeeb96d18519c2a090bdcd8df8f3 return; } if (aTab.group && aTab.group.id === aGroup.id) { -@@ -5721,6 +5856,8 @@ +@@ -5721,6 +5856,9 @@ moveActionCallback(); + ZenWorkspaces._makeSureEmptyTabIsLast(); ++ gZenViewSplitter._maybeRemoveFakeBrowser(); + // Clear tabs cache after moving nodes because the order of tabs may have // changed. this.tabContainer._invalidateCachedTabs(); -@@ -5771,7 +5908,7 @@ +@@ -5771,7 +5909,7 @@ createLazyBrowser, }; @@ -562,7 +563,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..a05cbeeb96d18519c2a090bdcd8df8f3 if (aIndex < numPinned || (aTab.pinned && aIndex == numPinned)) { params.pinned = true; } -@@ -7415,6 +7552,7 @@ +@@ -7415,6 +7553,7 @@ aWebProgress.isTopLevel ) { this.mTab.setAttribute("busy", "true"); @@ -570,7 +571,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..a05cbeeb96d18519c2a090bdcd8df8f3 gBrowser._tabAttrModified(this.mTab, ["busy"]); this.mTab._notselectedsinceload = !this.mTab.selected; } -@@ -8381,7 +8519,7 @@ var TabContextMenu = { +@@ -8381,7 +8520,7 @@ var TabContextMenu = { ); contextUnpinSelectedTabs.hidden = !this.contextTab.pinned || !multiselectionContext; @@ -579,7 +580,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..a05cbeeb96d18519c2a090bdcd8df8f3 // Move Tab items let contextMoveTabOptions = document.getElementById( "context_moveTabOptions" -@@ -8414,7 +8552,7 @@ var TabContextMenu = { +@@ -8414,7 +8553,7 @@ var TabContextMenu = { let contextMoveTabToStart = document.getElementById("context_moveToStart"); let isFirstTab = tabsToMove[0] == visibleTabs[0] || @@ -588,7 +589,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..a05cbeeb96d18519c2a090bdcd8df8f3 contextMoveTabToStart.disabled = isFirstTab && allSelectedTabsAdjacent; document.getElementById("context_openTabInWindow").disabled = -@@ -8647,6 +8785,7 @@ var TabContextMenu = { +@@ -8647,6 +8786,7 @@ var TabContextMenu = { if (this.contextTab.multiselected) { gBrowser.removeMultiSelectedTabs(); } else { From 148c9661c2a1f8c86d7daaf40a306c6963bd216e Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Wed, 5 Mar 2025 20:08:35 +0100 Subject: [PATCH 036/127] Refactor tab movement logic in ZenViewSplitter; ensure empty tab is last and adjust fake browser removal behavior --- .../tabbrowser/content/tabbrowser-js.patch | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/browser/components/tabbrowser/content/tabbrowser-js.patch b/src/browser/components/tabbrowser/content/tabbrowser-js.patch index 95c664b4b..96cbe160e 100644 --- a/src/browser/components/tabbrowser/content/tabbrowser-js.patch +++ b/src/browser/components/tabbrowser/content/tabbrowser-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js -index 628aa6596627c85efe361fc1ece8fd58f7ee653e..1cd7343818d25e40d4a441f70307f7ce7ff98054 100644 +index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe122b7900f1 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js @@ -412,11 +412,50 @@ @@ -544,17 +544,18 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..1cd7343818d25e40d4a441f70307f7ce return; } if (aTab.group && aTab.group.id === aGroup.id) { -@@ -5721,6 +5856,9 @@ +@@ -5721,6 +5856,10 @@ moveActionCallback(); + ZenWorkspaces._makeSureEmptyTabIsLast(); -+ gZenViewSplitter._maybeRemoveFakeBrowser(); ++ gZenViewSplitter._maybeRemoveFakeBrowser(false); ++ gZenViewSplitter._canDrop = false; + // Clear tabs cache after moving nodes because the order of tabs may have // changed. this.tabContainer._invalidateCachedTabs(); -@@ -5771,7 +5909,7 @@ +@@ -5771,7 +5910,7 @@ createLazyBrowser, }; @@ -563,7 +564,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..1cd7343818d25e40d4a441f70307f7ce if (aIndex < numPinned || (aTab.pinned && aIndex == numPinned)) { params.pinned = true; } -@@ -7415,6 +7553,7 @@ +@@ -7415,6 +7554,7 @@ aWebProgress.isTopLevel ) { this.mTab.setAttribute("busy", "true"); @@ -571,7 +572,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..1cd7343818d25e40d4a441f70307f7ce gBrowser._tabAttrModified(this.mTab, ["busy"]); this.mTab._notselectedsinceload = !this.mTab.selected; } -@@ -8381,7 +8520,7 @@ var TabContextMenu = { +@@ -8381,7 +8521,7 @@ var TabContextMenu = { ); contextUnpinSelectedTabs.hidden = !this.contextTab.pinned || !multiselectionContext; @@ -580,7 +581,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..1cd7343818d25e40d4a441f70307f7ce // Move Tab items let contextMoveTabOptions = document.getElementById( "context_moveTabOptions" -@@ -8414,7 +8553,7 @@ var TabContextMenu = { +@@ -8414,7 +8554,7 @@ var TabContextMenu = { let contextMoveTabToStart = document.getElementById("context_moveToStart"); let isFirstTab = tabsToMove[0] == visibleTabs[0] || @@ -589,7 +590,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..1cd7343818d25e40d4a441f70307f7ce contextMoveTabToStart.disabled = isFirstTab && allSelectedTabsAdjacent; document.getElementById("context_openTabInWindow").disabled = -@@ -8647,6 +8786,7 @@ var TabContextMenu = { +@@ -8647,6 +8787,7 @@ var TabContextMenu = { if (this.contextTab.multiselected) { gBrowser.removeMultiSelectedTabs(); } else { From 43da147d44666c77e8971aa8ac379862f11d9635 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Wed, 5 Mar 2025 20:17:49 +0100 Subject: [PATCH 037/127] Fix event coordinate check in ZenViewSplitter; use screenX and screenY instead of clickX and clientY --- l10n | 2 +- src/browser/base/zen-components/ZenViewSplitter.mjs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/l10n b/l10n index 92e05a383..b109ad083 160000 --- a/l10n +++ b/l10n @@ -1 +1 @@ -Subproject commit 92e05a383d535da1049577744f462709c63553e8 +Subproject commit b109ad0835e08402fe76f8765789966139ebb432 diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index 8167cd6f1..fce9f55fa 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -261,7 +261,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { (fakeBrowserRect && event.clientX > fakeBrowserRect.left && event.clientX < fakeBrowserRect.left + fakeBrowserRect.width) || - (event.clickX === 0 && event.clientY === 0) // It's equivalent to 0 if the event has been dropped + (event.screenX === 0 && event.screenY === 0) // It's equivalent to 0 if the event has been dropped ) { return; } From 8d3b9098c09898872eebcbf4b0614552b829aeb6 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Wed, 5 Mar 2025 21:32:47 +0100 Subject: [PATCH 038/127] Adjust URL bar container height for breakout state and remove redundant width/height calculations in URL bar styles --- .../base/content/zen-styles/zen-tabs/vertical-tabs.css | 5 ++--- src/browser/base/content/zen-styles/zen-urlbar.css | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css index 5e272a97d..7ffe00908 100644 --- a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css +++ b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css @@ -94,9 +94,8 @@ padding: 6px !important; } - & #urlbar-container, - & #urlbar { - --urlbar-container-height: 40px; + & #urlbar-container[breakout='true']:has([zen-floating-urlbar='true']) { + --urlbar-container-height: 36px !important; --urlbar-height: 38px !important; } diff --git a/src/browser/base/content/zen-styles/zen-urlbar.css b/src/browser/base/content/zen-styles/zen-urlbar.css index e7d1d2fd3..4b633a6aa 100644 --- a/src/browser/base/content/zen-styles/zen-urlbar.css +++ b/src/browser/base/content/zen-styles/zen-urlbar.css @@ -98,8 +98,6 @@ .urlbar-page-action, #tracking-protection-icon-container { - width: calc(var(--urlbar-min-height) - 6 * var(--urlbar-container-padding)) !important; - height: calc(var(--urlbar-min-height) - 6 * var(--urlbar-container-padding)) !important; margin-top: auto !important; margin-bottom: auto !important; } From ff4fe92c9f9a3b77d425928d14c04d6019a55c45 Mon Sep 17 00:00:00 2001 From: Quoc-Anh Nguyen <9426721+imcvampire@users.noreply.github.com> Date: Thu, 6 Mar 2025 03:10:51 +0200 Subject: [PATCH 039/127] Update README.md: fix small typo on version format Signed-off-by: Quoc-Anh Nguyen <9426721+imcvampire@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6c0f170f0..dfa52dcdd 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ We keep track of how many issues are closed at the end of the month in [docs/iss ### Versioning -Zen uses [Semantic Versioning](https://semver.org/), meaning versions are displayed as `a.bc.d` where: +Zen uses [Semantic Versioning](https://semver.org/), meaning versions are displayed as `a.b.cd` where: - `a` is the major version - `b` is the minor version From 98084457ff688622f1fa69bb7a91f7c150d03944 Mon Sep 17 00:00:00 2001 From: dillontkh <> Date: Thu, 6 Mar 2025 19:22:13 +0800 Subject: [PATCH 040/127] Fix compact mode top toolbar hiding prematurely --- src/browser/base/zen-components/ZenCompactMode.mjs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/browser/base/zen-components/ZenCompactMode.mjs b/src/browser/base/zen-components/ZenCompactMode.mjs index 9d1309bf3..2bbade9ed 100644 --- a/src/browser/base/zen-components/ZenCompactMode.mjs +++ b/src/browser/base/zen-components/ZenCompactMode.mjs @@ -368,6 +368,12 @@ var gZenCompactModeManager = { } } + // When moving the cursor between the url bar and bookmarks, or in-between bookmarks in the bookmark bar, the + // mouseLeave event is triggered without a relatedTarget. + if (event.relatedTarget == null) { + return; + } + // If it's a child element but not the target, ignore the event if (target.contains(event.explicitOriginalTarget) && event.explicitOriginalTarget !== target) { return; From 713ceab89f45ec34182a8eb164dab033efff849d Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Thu, 6 Mar 2025 12:50:42 +0100 Subject: [PATCH 041/127] Enhance styling and functionality in Zen components; adjust URL bar border radius, update tab unloading logic, and refine element separation settings --- src/browser/app/profile/zen-browser.js | 2 +- .../base/content/zen-styles/zen-decks.css | 10 +-- .../content/zen-styles/zen-sidebar-panels.css | 5 +- .../zen-styles/zen-tabs/vertical-tabs.css | 2 +- .../base/content/zen-styles/zen-theme.css | 4 +- .../base/content/zen-styles/zen-urlbar.css | 1 + .../base/content/zen-styles/zen-welcome.css | 10 +-- .../zen-components/ZenGradientGenerator.mjs | 2 +- .../base/zen-components/ZenTabUnloader.mjs | 3 +- .../base/zen-components/ZenViewSplitter.mjs | 2 +- .../base/zen-components/ZenWelcome.mjs | 12 ++-- .../base/zen-components/ZenWorkspaces.mjs | 2 + .../extensions/parent/ext-tabs-js.patch | 12 ++++ .../tabbrowser/content/tabs-js.patch | 71 ++++++++++--------- src/browser/themes/shared/zen-icons/icons.css | 3 +- .../shared/zen-icons/lin/accessibility.svg | 2 +- .../zen-icons/lin/add-to-dictionary.svg | 2 +- .../shared/zen-icons/lin/arrow-down.svg | 2 +- .../shared/zen-icons/lin/arrow-left.svg | 2 +- .../shared/zen-icons/lin/arrow-right.svg | 2 +- .../themes/shared/zen-icons/lin/arrow-up.svg | 2 +- .../shared/zen-icons/lin/audio-save.svg | 2 +- .../zen-icons/lin/autoplay-media-blocked.svg | 2 +- .../shared/zen-icons/lin/autoplay-media.svg | 2 +- .../themes/shared/zen-icons/lin/back.svg | 2 +- .../shared/zen-icons/lin/bookmark-hollow.svg | 2 +- .../zen-icons/lin/bookmark-star-on-tray.svg | 2 +- .../themes/shared/zen-icons/lin/bookmark.svg | 2 +- .../shared/zen-icons/lin/camera-blocked.svg | 2 +- .../themes/shared/zen-icons/lin/camera.svg | 2 +- .../themes/shared/zen-icons/lin/canvas.svg | 2 +- .../themes/shared/zen-icons/lin/checkmark.svg | 2 +- .../themes/shared/zen-icons/lin/chevron.svg | 2 +- .../themes/shared/zen-icons/lin/close-all.svg | 2 +- .../themes/shared/zen-icons/lin/close.svg | 2 +- .../shared/zen-icons/lin/container-tab.svg | 2 +- .../themes/shared/zen-icons/lin/customize.svg | 2 +- .../lin/desktop-notification-blocked.svg | 2 +- .../zen-icons/lin/desktop-notification.svg | 2 +- .../themes/shared/zen-icons/lin/developer.svg | 2 +- .../themes/shared/zen-icons/lin/downloads.svg | 2 +- .../shared/zen-icons/lin/drag-indicator.svg | 2 +- .../shared/zen-icons/lin/duplicate-tab.svg | 2 +- .../themes/shared/zen-icons/lin/edit-copy.svg | 2 +- .../themes/shared/zen-icons/lin/edit-cut.svg | 2 +- .../shared/zen-icons/lin/edit-delete.svg | 2 +- .../shared/zen-icons/lin/edit-paste.svg | 2 +- .../themes/shared/zen-icons/lin/edit-redo.svg | 2 +- .../shared/zen-icons/lin/edit-select-all.svg | 2 +- .../shared/zen-icons/lin/edit-theme.svg | 2 +- .../themes/shared/zen-icons/lin/edit-undo.svg | 2 +- .../themes/shared/zen-icons/lin/edit.svg | 2 +- .../shared/zen-icons/lin/essential-add.svg | 2 +- .../shared/zen-icons/lin/essential-remove.svg | 2 +- .../shared/zen-icons/lin/expand-sidebar.svg | 2 +- .../themes/shared/zen-icons/lin/ext-link.svg | 2 +- .../zen-icons/lin/extension-blocked.svg | 2 +- .../themes/shared/zen-icons/lin/extension.svg | 2 +- .../themes/shared/zen-icons/lin/folder.svg | 2 +- .../themes/shared/zen-icons/lin/forget.svg | 2 +- .../themes/shared/zen-icons/lin/forward.svg | 2 +- .../shared/zen-icons/lin/fullscreen-exit.svg | 2 +- .../shared/zen-icons/lin/fullscreen.svg | 2 +- .../shared/zen-icons/lin/geo-blocked.svg | 2 +- .../themes/shared/zen-icons/lin/geo.svg | 2 +- .../themes/shared/zen-icons/lin/help.svg | 2 +- .../themes/shared/zen-icons/lin/history.svg | 2 +- .../themes/shared/zen-icons/lin/home.svg | 2 +- .../shared/zen-icons/lin/image-copy.svg | 2 +- .../shared/zen-icons/lin/image-open.svg | 2 +- .../shared/zen-icons/lin/image-save.svg | 2 +- .../themes/shared/zen-icons/lin/info.svg | 2 +- .../themes/shared/zen-icons/lin/inspect.svg | 2 +- .../themes/shared/zen-icons/lin/library.svg | 2 +- .../themes/shared/zen-icons/lin/link.svg | 2 +- .../themes/shared/zen-icons/lin/manage.svg | 2 +- .../shared/zen-icons/lin/media-loop.svg | 2 +- .../shared/zen-icons/lin/media-mute.svg | 2 +- .../shared/zen-icons/lin/media-pause.svg | 2 +- .../themes/shared/zen-icons/lin/media-pip.svg | 2 +- .../shared/zen-icons/lin/media-play.svg | 2 +- .../shared/zen-icons/lin/media-speed.svg | 2 +- .../shared/zen-icons/lin/media-unmute.svg | 2 +- .../themes/shared/zen-icons/lin/menu-bar.svg | 2 +- .../themes/shared/zen-icons/lin/menu.svg | 2 +- .../zen-icons/lin/microphone-blocked.svg | 2 +- .../shared/zen-icons/lin/microphone.svg | 2 +- .../themes/shared/zen-icons/lin/move-tab.svg | 2 +- .../shared/zen-icons/lin/new-tab-image.svg | 2 +- .../themes/shared/zen-icons/lin/open.svg | 2 +- .../shared/zen-icons/lin/page-portrait.svg | 2 +- .../themes/shared/zen-icons/lin/palette.svg | 2 +- .../themes/shared/zen-icons/lin/passwords.svg | 2 +- .../shared/zen-icons/lin/paste-and-go.svg | 2 +- .../shared/zen-icons/lin/permissions.svg | 2 +- .../lin/persistent-storage-blocked.svg | 2 +- .../zen-icons/lin/persistent-storage.svg | 2 +- .../themes/shared/zen-icons/lin/pin.svg | 2 +- .../themes/shared/zen-icons/lin/plus.svg | 2 +- .../themes/shared/zen-icons/lin/popup.svg | 2 +- .../themes/shared/zen-icons/lin/print.svg | 2 +- .../shared/zen-icons/lin/private-window.svg | 2 +- .../shared/zen-icons/lin/privateBrowsing.svg | 2 +- .../shared/zen-icons/lin/reader-mode.svg | 2 +- .../themes/shared/zen-icons/lin/reload.svg | 2 +- .../themes/shared/zen-icons/lin/report.svg | 2 +- .../themes/shared/zen-icons/lin/save.svg | 2 +- .../shared/zen-icons/lin/screen-blocked.svg | 2 +- .../themes/shared/zen-icons/lin/screen.svg | 2 +- .../shared/zen-icons/lin/screenshot.svg | 2 +- .../shared/zen-icons/lin/search-glass.svg | 2 +- .../shared/zen-icons/lin/search-page.svg | 2 +- .../shared/zen-icons/lin/security-broken.svg | 2 +- .../shared/zen-icons/lin/security-warning.svg | 2 +- .../themes/shared/zen-icons/lin/security.svg | 2 +- .../shared/zen-icons/lin/send-to-device.svg | 2 +- .../themes/shared/zen-icons/lin/settings.svg | 2 +- .../themes/shared/zen-icons/lin/share.svg | 2 +- .../themes/shared/zen-icons/lin/sidebar.svg | 2 +- .../shared/zen-icons/lin/sidebars-right.svg | 2 +- .../shared/zen-icons/lin/source-code.svg | 2 +- .../shared/zen-icons/lin/spell-check.svg | 2 +- .../themes/shared/zen-icons/lin/split.svg | 2 +- .../zen-icons/lin/tab-audio-blocked-small.svg | 2 +- .../zen-icons/lin/tab-audio-muted-small.svg | 2 +- .../zen-icons/lin/tab-audio-playing-small.svg | 2 +- .../themes/shared/zen-icons/lin/tab.svg | 2 +- .../shared/zen-icons/lin/tool-profiler.svg | 2 +- .../zen-icons/lin/tracking-protection.svg | 2 +- .../shared/zen-icons/lin/translations.svg | 2 +- .../themes/shared/zen-icons/lin/unpin.svg | 2 +- .../shared/zen-icons/lin/video-open.svg | 2 +- .../shared/zen-icons/lin/video-save.svg | 2 +- .../themes/shared/zen-icons/lin/window.svg | 2 +- .../shared/zen-icons/lin/xr-blocked.svg | 2 +- .../themes/shared/zen-icons/lin/xr.svg | 2 +- .../shared/zen-icons/lin/zoom-control.svg | 2 +- .../themes/shared/zen-icons/lin/zoom-out.svg | 2 +- 138 files changed, 196 insertions(+), 191 deletions(-) create mode 100644 src/browser/components/extensions/parent/ext-tabs-js.patch diff --git a/src/browser/app/profile/zen-browser.js b/src/browser/app/profile/zen-browser.js index 62aa95df0..b9ec6fd81 100644 --- a/src/browser/app/profile/zen-browser.js +++ b/src/browser/app/profile/zen-browser.js @@ -81,7 +81,7 @@ pref('zen.tabs.vertical', true); pref('zen.tabs.vertical.right-side', false); pref('zen.tabs.rename-tabs', true); pref('zen.theme.accent-color', "#ffb787"); -pref('zen.theme.content-element-separation', 10); // In pixels +pref('zen.theme.content-element-separation', 8); // In pixels pref('zen.theme.gradient', true); pref('zen.theme.gradient.show-custom-colors', false); pref('zen.theme.essentials-favicon-bg', true); diff --git a/src/browser/base/content/zen-styles/zen-decks.css b/src/browser/base/content/zen-styles/zen-decks.css index 7ba7975f5..80e26070d 100644 --- a/src/browser/base/content/zen-styles/zen-decks.css +++ b/src/browser/base/content/zen-styles/zen-decks.css @@ -29,7 +29,7 @@ #tabbrowser-tabpanels[zen-split-view='true'] > [zen-split='true'], #zen-splitview-dropzone { flex: 1; - margin: var(--zen-split-column-gap) calc(var(--zen-split-row-gap) + 1px) !important; + margin: var(--zen-split-column-gap) var(--zen-split-row-gap) !important; margin-bottom: 0 !important; margin-left: 0 !important; position: absolute !important; @@ -48,7 +48,7 @@ } #tabbrowser-tabbox:has(#tabbrowser-tabpanels[zen-split-view='true']) { - --zen-split-row-gap: calc(var(--zen-element-separation) + 1px); + --zen-split-row-gap: var(--zen-element-separation); --zen-split-column-gap: calc(var(--zen-element-separation) + 1px); margin-right: calc(-1 * var(--zen-split-column-gap)); } @@ -90,12 +90,6 @@ pointer-events: all; } -.zen-split-view-splitter[orient='vertical'] { - width: var(--zen-split-row-gap); - margin-left: calc(var(--zen-split-row-gap) / -2); - cursor: ew-resize; -} - .zen-split-view-splitter[orient='horizontal'] { height: var(--zen-split-column-gap); cursor: ns-resize; diff --git a/src/browser/base/content/zen-styles/zen-sidebar-panels.css b/src/browser/base/content/zen-styles/zen-sidebar-panels.css index d82053403..a22fd9aaa 100644 --- a/src/browser/base/content/zen-styles/zen-sidebar-panels.css +++ b/src/browser/base/content/zen-styles/zen-sidebar-panels.css @@ -114,9 +114,10 @@ &:is(.zen-split-view-splitter[orient='vertical']) { /* Bit of a hacky solution, but it works */ - width: calc(var(--zen-element-separation) - 3px); - margin-left: calc(-1 * var(--zen-element-separation) / 2 - 2px); + width: var(--zen-split-row-gap); + margin-left: calc(var(--zen-element-separation) * -1 - 1px); height: unset; + cursor: ew-resize; } &::before { diff --git a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css index 7ffe00908..ccd32fe57 100644 --- a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css +++ b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css @@ -1101,7 +1101,7 @@ &::after { content: ""; inset: -50%; - filter: blur(15px); + filter: blur(15px) brightness(1.2); position: absolute; background-size: 100% 100%; background-clip: padding-box; diff --git a/src/browser/base/content/zen-styles/zen-theme.css b/src/browser/base/content/zen-styles/zen-theme.css index 9dfcc3d99..933260e21 100644 --- a/src/browser/base/content/zen-styles/zen-theme.css +++ b/src/browser/base/content/zen-styles/zen-theme.css @@ -79,7 +79,7 @@ --focus-outline-color: var(--button-bgcolor) !important; --toolbarbutton-icon-fill-attention: var(--zen-primary-color) !important; - --toolbarbutton-icon-fill: light-dark(rgb(57, 57, 58), rgb(251, 251, 254)) !important; + --toolbarbutton-icon-fill: light-dark(rgba(57, 57, 58, .6), rgba(251, 251, 254, .6)) !important; --button-primary-bgcolor: var(--in-content-primary-button-background) !important; --button-primary-hover-bgcolor: var(--in-content-primary-button-background-hover) !important; @@ -155,7 +155,7 @@ --input-bgcolor: var(--zen-colors-tertiary) !important; --input-border-color: var(--zen-input-border-color) !important; - --zen-themed-toolbar-bg: light-dark(var(--zen-branding-bg), #161616); + --zen-themed-toolbar-bg: light-dark(rgb(240, 240, 244), #161616); --zen-themed-toolbar-bg-transparent: light-dark(var(--zen-branding-bg), #161616); --zen-workspace-indicator-height: 45px; diff --git a/src/browser/base/content/zen-styles/zen-urlbar.css b/src/browser/base/content/zen-styles/zen-urlbar.css index 4b633a6aa..75b27837e 100644 --- a/src/browser/base/content/zen-styles/zen-urlbar.css +++ b/src/browser/base/content/zen-styles/zen-urlbar.css @@ -127,6 +127,7 @@ box-shadow: 0px 0px 90px -10px rgba(0, 0, 0, 0.6) !important; border: 1px solid hsla(0, 0%, 100%, 0.1) !important; backdrop-filter: none !important; + border-radius: 1rem !important; } #urlbar-go-button { diff --git a/src/browser/base/content/zen-styles/zen-welcome.css b/src/browser/base/content/zen-styles/zen-welcome.css index f67fa8eb2..4d1d4c092 100644 --- a/src/browser/base/content/zen-styles/zen-welcome.css +++ b/src/browser/base/content/zen-styles/zen-welcome.css @@ -24,10 +24,6 @@ list-style-image: url(chrome://browser/skin/zen-icons/forward.svg); position: absolute; bottom: 10%; - - .button-icon { - filter: invert(1); - } } #zen-welcome-title { @@ -251,14 +247,10 @@ &[visuallyselected] { transform: scale(1.04); - - & .tab-background { - box-shadow: var(--zen-big-shadow); - } } & .tab-background::after { - filter: blur(30px) !important; + filter: blur(30px) brightness(1.2); } } } diff --git a/src/browser/base/zen-components/ZenGradientGenerator.mjs b/src/browser/base/zen-components/ZenGradientGenerator.mjs index 5d9f58a6b..fc18114e5 100644 --- a/src/browser/base/zen-components/ZenGradientGenerator.mjs +++ b/src/browser/base/zen-components/ZenGradientGenerator.mjs @@ -863,7 +863,7 @@ getToolbarModifiedBase() { return this.isDarkMode ? 'color-mix(in srgb, var(--zen-themed-toolbar-bg) 80%, #fff 20%)' - : 'color-mix(in srgb, var(--zen-themed-toolbar-bg) 95%, #000 5%)'; + : 'color-mix(in srgb, var(--zen-themed-toolbar-bg) 95%, #000 6%)'; } getSingleRGBColor(color, forToolbar = false) { diff --git a/src/browser/base/zen-components/ZenTabUnloader.mjs b/src/browser/base/zen-components/ZenTabUnloader.mjs index bd733006c..f305ad0cb 100644 --- a/src/browser/base/zen-components/ZenTabUnloader.mjs +++ b/src/browser/base/zen-components/ZenTabUnloader.mjs @@ -274,7 +274,8 @@ (tab.pictureinpicture && !ignoreTimestamp) || (tab.soundPlaying && !ignoreTimestamp) || (tab.zenIgnoreUnload && !ignoreTimestamp) || - excludedUrls.some((url) => url.test(tab.linkedBrowser?.currentURI.spec)) + (excludedUrls.some((url) => url.test(tab.linkedBrowser?.currentURI.spec)) + && tab.linkedBrowser?.currentURI.spec !== 'about:blank') ) { return false; } diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index fce9f55fa..b327fcc17 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -1227,7 +1227,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { this.tabBrowserPanel.setAttribute('zen-split-resizing', true); const isVertical = event.target.getAttribute('orient') === 'vertical'; const dimension = isVertical ? 'width' : 'height'; - const clientAxis = isVertical ? 'screenX' : 'screenY'; + const clientAxis = isVertical ? 'clientX' : 'clientY'; const gridIdx = parseInt(event.target.getAttribute('gridIdx')); const startPosition = event[clientAxis]; diff --git a/src/browser/base/zen-components/ZenWelcome.mjs b/src/browser/base/zen-components/ZenWelcome.mjs index a7a285f56..32bd7f6e1 100644 --- a/src/browser/base/zen-components/ZenWelcome.mjs +++ b/src/browser/base/zen-components/ZenWelcome.mjs @@ -335,7 +335,7 @@ - + @@ -345,17 +345,17 @@ - + - + - + @@ -370,12 +370,12 @@ - + - + diff --git a/src/browser/base/zen-components/ZenWorkspaces.mjs b/src/browser/base/zen-components/ZenWorkspaces.mjs index 7e8ca9969..e14d91a9e 100644 --- a/src/browser/base/zen-components/ZenWorkspaces.mjs +++ b/src/browser/base/zen-components/ZenWorkspaces.mjs @@ -614,6 +614,8 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { if (currentTab.pinned) { this.selectEmptyTab(); try { + console.log(currentTab) + console.log(currentTab.linkedBrowser?.currentURI.spec) gZenTabUnloader.explicitUnloadTabs([currentTab]); } catch (e) { console.error('ZenWorkspaces: Error unloading tab', e); diff --git a/src/browser/components/extensions/parent/ext-tabs-js.patch b/src/browser/components/extensions/parent/ext-tabs-js.patch new file mode 100644 index 000000000..a0bc87efd --- /dev/null +++ b/src/browser/components/extensions/parent/ext-tabs-js.patch @@ -0,0 +1,12 @@ +diff --git a/browser/components/extensions/parent/ext-tabs.js b/browser/components/extensions/parent/ext-tabs.js +index b47f0510e32d788dfe7c3109474c4512c9900d4a..49697125a2998bbd50d87c54e2c5974baaf9a7e2 100644 +--- a/browser/components/extensions/parent/ext-tabs.js ++++ b/browser/components/extensions/parent/ext-tabs.js +@@ -468,6 +468,7 @@ this.tabs = class extends ExtensionAPIPersistent { + } + + let tab = tabManager.getWrapper(event.originalTarget); ++ if (!tab) return; + + let changeInfo = {}; + for (let prop of needed) { diff --git a/src/browser/components/tabbrowser/content/tabs-js.patch b/src/browser/components/tabbrowser/content/tabs-js.patch index f4369f941..44e4b7c45 100644 --- a/src/browser/components/tabbrowser/content/tabs-js.patch +++ b/src/browser/components/tabbrowser/content/tabs-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js -index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de9d5b6d33 100644 +index fa96568d366fd3608f9bd583fa793150bd815c8b..1e007c37cd204c63afad24c8b6d9201e6a02da2d 100644 --- a/browser/components/tabbrowser/content/tabs.js +++ b/browser/components/tabbrowser/content/tabs.js @@ -94,7 +94,7 @@ @@ -37,17 +37,18 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de let tabsPerRow = 0; let position = 0; for (let pinnedTab of pinnedTabs) { -@@ -883,6 +884,9 @@ +@@ -883,6 +884,10 @@ } let draggedTab = event.dataTransfer.mozGetDataAt(TAB_DROP_TYPE, 0); + if (draggedTab && effects === "move") { + gZenPinnedTabManager.applyDragoverClass(event, draggedTab); ++ gZenViewSplitter.onBrowserDragEndToSplit(event); + } if ( (effects == "move" || effects == "copy") && this == draggedTab.container && -@@ -996,6 +1000,14 @@ +@@ -996,6 +1001,14 @@ this._tabDropIndicator.hidden = true; event.stopPropagation(); @@ -62,7 +63,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de if (draggedTab && dropEffect == "copy") { // copy the dropped tab (wherever it's from) let newIndex = this._getDropIndex(event); -@@ -1034,10 +1046,11 @@ +@@ -1034,10 +1047,11 @@ } } else { let pinned = draggedTab.pinned; @@ -78,7 +79,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de ); let size = this.verticalMode ? "height" : "width"; let screenAxis = this.verticalMode ? "screenY" : "screenX"; -@@ -1114,7 +1127,7 @@ +@@ -1114,7 +1128,7 @@ let postTransitionCleanup = () => { tab.removeAttribute("tabdrop-samewindow"); @@ -87,7 +88,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de if (dropIndex !== false) { gBrowser.moveTabTo(tab, dropIndex); if (!directionForward) { -@@ -1122,7 +1135,7 @@ +@@ -1122,7 +1136,7 @@ } } }; @@ -96,7 +97,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de postTransitionCleanup(); } else { let onTransitionEnd = transitionendEvent => { -@@ -1279,13 +1292,23 @@ +@@ -1279,13 +1293,23 @@ return; } @@ -122,7 +123,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de ) { delete draggedTab._dragData; return; -@@ -1517,7 +1540,7 @@ +@@ -1517,7 +1541,7 @@ } get newTabButton() { @@ -131,7 +132,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de } get verticalMode() { -@@ -1537,28 +1560,40 @@ +@@ -1537,28 +1561,40 @@ if (this.#allTabs) { return this.#allTabs; } @@ -180,7 +181,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de return children.filter(node => node.tagName == "tab-group"); } -@@ -1579,7 +1614,7 @@ +@@ -1579,7 +1615,7 @@ */ get visibleTabs() { if (!this.#visibleTabs) { @@ -189,7 +190,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de } return this.#visibleTabs; } -@@ -1613,10 +1648,8 @@ +@@ -1613,10 +1649,8 @@ return this.#focusableItems; } @@ -202,7 +203,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de let focusableItems = []; for (let child of children) { -@@ -1632,6 +1665,7 @@ +@@ -1632,6 +1666,7 @@ } this.#focusableItems = [ @@ -210,7 +211,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de ...verticalPinnedTabsContainer.children, ...focusableItems, ]; -@@ -1642,6 +1676,7 @@ +@@ -1642,6 +1677,7 @@ _invalidateCachedTabs() { this.#allTabs = null; this._invalidateCachedVisibleTabs(); @@ -218,7 +219,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de } _invalidateCachedVisibleTabs() { -@@ -1656,8 +1691,8 @@ +@@ -1656,8 +1692,8 @@ #isContainerVerticalPinnedExpanded(tab) { return ( this.verticalMode && @@ -229,7 +230,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de ); } -@@ -1672,7 +1707,7 @@ +@@ -1672,7 +1708,7 @@ if (node == null) { // We have a container for non-tab elements at the end of the scrollbox. @@ -238,7 +239,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de } node.before(tab); -@@ -1772,7 +1807,7 @@ +@@ -1772,7 +1808,7 @@ // There are separate "new tab" buttons for horizontal tabs toolbar, vertical tabs and // for when the tab strip is overflowed (which is shared by vertical and horizontal tabs); // Attach the long click popup to all of them. @@ -247,7 +248,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de const newTab2 = this.newTabButton; const newTabVertical = document.getElementById( "vertical-tabs-newtab-button" -@@ -1855,7 +1890,7 @@ +@@ -1855,7 +1891,7 @@ let rect = ele => { return window.windowUtils.getBoundsWithoutFlushing(ele); }; @@ -256,7 +257,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de if (tab && rect(tab).width <= this._tabClipWidth) { this.setAttribute("closebuttons", "activetab"); } else { -@@ -1867,10 +1902,12 @@ +@@ -1867,10 +1903,12 @@ _handleTabSelect(aInstant) { let selectedTab = this.selectedItem; @@ -269,7 +270,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de selectedTab._notselectedsinceload = false; } -@@ -1882,7 +1919,7 @@ +@@ -1882,7 +1920,7 @@ return; } @@ -278,7 +279,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de if (!tabs.length) { return; } -@@ -1918,7 +1955,7 @@ +@@ -1918,7 +1956,7 @@ if (isEndTab && !this._hasTabTempMaxWidth) { return; } @@ -287,7 +288,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de // Force tabs to stay the same width, unless we're closing the last tab, // which case we need to let them expand just enough so that the overall // tabbar width is the same. -@@ -1933,7 +1970,7 @@ +@@ -1933,7 +1971,7 @@ let tabsToReset = []; for (let i = numPinned; i < tabs.length; i++) { let tab = tabs[i]; @@ -296,7 +297,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de if (!isEndTab) { // keep tabs the same width tab.style.transition = "none"; -@@ -1999,16 +2036,15 @@ +@@ -1999,16 +2037,15 @@ // Move pinned tabs to another container when the tabstrip is toggled to vertical // and when session restore code calls _positionPinnedTabs; update styling whenever // the number of pinned tabs changes. @@ -319,7 +320,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de } } -@@ -2016,9 +2052,7 @@ +@@ -2016,9 +2053,7 @@ } _resetVerticalPinnedTabs() { @@ -330,7 +331,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de if (!verticalTabsContainer.children.length) { return; -@@ -2031,8 +2065,8 @@ +@@ -2031,8 +2066,8 @@ } _positionPinnedTabs() { @@ -341,7 +342,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de let absPositionHorizontalTabs = this.overflowing && tabs.length > numPinned && numPinned > 0; -@@ -2041,7 +2075,7 @@ +@@ -2041,7 +2076,7 @@ if (this.verticalMode) { this._updateVerticalPinnedTabs(); @@ -350,7 +351,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de let layoutData = this._pinnedTabsLayoutCache; let uiDensity = document.documentElement.getAttribute("uidensity"); if (!layoutData || layoutData.uiDensity != uiDensity) { -@@ -2113,7 +2147,7 @@ +@@ -2113,7 +2148,7 @@ return; } @@ -359,7 +360,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de let directionX = screenX > dragData.animLastScreenX; let directionY = screenY > dragData.animLastScreenY; -@@ -2121,7 +2155,7 @@ +@@ -2121,7 +2156,7 @@ dragData.animLastScreenX = screenX; let { width: tabWidth, height: tabHeight } = @@ -368,7 +369,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de let shiftSizeX = tabWidth * movingTabs.length; let shiftSizeY = tabHeight; dragData.tabWidth = tabWidth; -@@ -2296,10 +2330,11 @@ +@@ -2296,10 +2331,11 @@ } let pinned = draggedTab.pinned; @@ -384,7 +385,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de ); if (this.#rtlMode) { -@@ -2347,8 +2382,12 @@ +@@ -2347,8 +2383,12 @@ (lastMovingTabScreen + tabSize); translate = Math.min(Math.max(translate, firstBound), lastBound); @@ -399,7 +400,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de } dragData.translatePos = translate; -@@ -2484,12 +2523,16 @@ +@@ -2484,12 +2524,16 @@ // Shift background tabs to leave a gap where the dragged tab // would currently be dropped. for (let tab of tabs) { @@ -417,7 +418,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de if (tab.group?.tabs[0] == tab) { tab.group.style.setProperty( "--tabgroup-dragover-transform", -@@ -2541,8 +2584,9 @@ +@@ -2541,8 +2585,9 @@ ); } @@ -429,7 +430,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de return; } -@@ -2553,6 +2597,7 @@ +@@ -2553,6 +2598,7 @@ tab.style.transform = ""; if (tab.group) { tab.group.style.removeProperty("--tabgroup-dragover-transform"); @@ -437,7 +438,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de } tab.removeAttribute("dragover-createGroup"); } -@@ -2604,7 +2649,7 @@ +@@ -2604,7 +2650,7 @@ movingTab._moveTogetherSelectedTabsData.newIndex = movingTabNewIndex; movingTab._moveTogetherSelectedTabsData.animate = false; }; @@ -446,7 +447,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de postTransitionCleanup(); } else { let onTransitionEnd = transitionendEvent => { -@@ -2707,9 +2752,9 @@ +@@ -2707,9 +2753,9 @@ function newIndex(aTab, index) { // Don't allow mixing pinned and unpinned tabs. if (aTab.pinned) { @@ -458,7 +459,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..2e28e3eba422e176c0536e6a6d0386de } } -@@ -2793,7 +2838,7 @@ +@@ -2793,7 +2839,7 @@ } _notifyBackgroundTab(aTab) { diff --git a/src/browser/themes/shared/zen-icons/icons.css b/src/browser/themes/shared/zen-icons/icons.css index 7c6ff2dca..c8c69e4e8 100644 --- a/src/browser/themes/shared/zen-icons/icons.css +++ b/src/browser/themes/shared/zen-icons/icons.css @@ -4,7 +4,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -.subviewbutton { +.subviewbutton, +#zen-welcome-start-button { -moz-context-properties: fill, fill-opacity !important; fill: currentColor !important; } diff --git a/src/browser/themes/shared/zen-icons/lin/accessibility.svg b/src/browser/themes/shared/zen-icons/lin/accessibility.svg index c840382d3..c39bc6515 100644 --- a/src/browser/themes/shared/zen-icons/lin/accessibility.svg +++ b/src/browser/themes/shared/zen-icons/lin/accessibility.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/add-to-dictionary.svg b/src/browser/themes/shared/zen-icons/lin/add-to-dictionary.svg index 3ee28ba35..afe095170 100644 --- a/src/browser/themes/shared/zen-icons/lin/add-to-dictionary.svg +++ b/src/browser/themes/shared/zen-icons/lin/add-to-dictionary.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/arrow-down.svg b/src/browser/themes/shared/zen-icons/lin/arrow-down.svg index 3fb328224..6e75be146 100644 --- a/src/browser/themes/shared/zen-icons/lin/arrow-down.svg +++ b/src/browser/themes/shared/zen-icons/lin/arrow-down.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/arrow-left.svg b/src/browser/themes/shared/zen-icons/lin/arrow-left.svg index f44352b46..5be52a566 100644 --- a/src/browser/themes/shared/zen-icons/lin/arrow-left.svg +++ b/src/browser/themes/shared/zen-icons/lin/arrow-left.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/arrow-right.svg b/src/browser/themes/shared/zen-icons/lin/arrow-right.svg index cff35212a..768e02585 100644 --- a/src/browser/themes/shared/zen-icons/lin/arrow-right.svg +++ b/src/browser/themes/shared/zen-icons/lin/arrow-right.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/arrow-up.svg b/src/browser/themes/shared/zen-icons/lin/arrow-up.svg index b206a3f9f..caff600fa 100644 --- a/src/browser/themes/shared/zen-icons/lin/arrow-up.svg +++ b/src/browser/themes/shared/zen-icons/lin/arrow-up.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/audio-save.svg b/src/browser/themes/shared/zen-icons/lin/audio-save.svg index 6b01002fb..2d585715a 100644 --- a/src/browser/themes/shared/zen-icons/lin/audio-save.svg +++ b/src/browser/themes/shared/zen-icons/lin/audio-save.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/autoplay-media-blocked.svg b/src/browser/themes/shared/zen-icons/lin/autoplay-media-blocked.svg index 8e2760962..f03cb44e4 100644 --- a/src/browser/themes/shared/zen-icons/lin/autoplay-media-blocked.svg +++ b/src/browser/themes/shared/zen-icons/lin/autoplay-media-blocked.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/autoplay-media.svg b/src/browser/themes/shared/zen-icons/lin/autoplay-media.svg index 12ef8fcf0..bc6915dd1 100644 --- a/src/browser/themes/shared/zen-icons/lin/autoplay-media.svg +++ b/src/browser/themes/shared/zen-icons/lin/autoplay-media.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/back.svg b/src/browser/themes/shared/zen-icons/lin/back.svg index d2c36f023..34bf4083c 100644 --- a/src/browser/themes/shared/zen-icons/lin/back.svg +++ b/src/browser/themes/shared/zen-icons/lin/back.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/bookmark-hollow.svg b/src/browser/themes/shared/zen-icons/lin/bookmark-hollow.svg index 80ee175f8..345191206 100644 --- a/src/browser/themes/shared/zen-icons/lin/bookmark-hollow.svg +++ b/src/browser/themes/shared/zen-icons/lin/bookmark-hollow.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/bookmark-star-on-tray.svg b/src/browser/themes/shared/zen-icons/lin/bookmark-star-on-tray.svg index 80ee175f8..345191206 100644 --- a/src/browser/themes/shared/zen-icons/lin/bookmark-star-on-tray.svg +++ b/src/browser/themes/shared/zen-icons/lin/bookmark-star-on-tray.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/bookmark.svg b/src/browser/themes/shared/zen-icons/lin/bookmark.svg index c00c201f1..611019bbe 100644 --- a/src/browser/themes/shared/zen-icons/lin/bookmark.svg +++ b/src/browser/themes/shared/zen-icons/lin/bookmark.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/camera-blocked.svg b/src/browser/themes/shared/zen-icons/lin/camera-blocked.svg index fc7df3492..3307817ec 100644 --- a/src/browser/themes/shared/zen-icons/lin/camera-blocked.svg +++ b/src/browser/themes/shared/zen-icons/lin/camera-blocked.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/camera.svg b/src/browser/themes/shared/zen-icons/lin/camera.svg index d8fd7902a..f9018a192 100644 --- a/src/browser/themes/shared/zen-icons/lin/camera.svg +++ b/src/browser/themes/shared/zen-icons/lin/camera.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/canvas.svg b/src/browser/themes/shared/zen-icons/lin/canvas.svg index 088d715e6..97fed1e79 100644 --- a/src/browser/themes/shared/zen-icons/lin/canvas.svg +++ b/src/browser/themes/shared/zen-icons/lin/canvas.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/checkmark.svg b/src/browser/themes/shared/zen-icons/lin/checkmark.svg index b2379ceba..b3b266741 100644 --- a/src/browser/themes/shared/zen-icons/lin/checkmark.svg +++ b/src/browser/themes/shared/zen-icons/lin/checkmark.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/chevron.svg b/src/browser/themes/shared/zen-icons/lin/chevron.svg index 43b683ae1..70fe59d32 100644 --- a/src/browser/themes/shared/zen-icons/lin/chevron.svg +++ b/src/browser/themes/shared/zen-icons/lin/chevron.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/close-all.svg b/src/browser/themes/shared/zen-icons/lin/close-all.svg index d4c6ae30a..72b8848c5 100644 --- a/src/browser/themes/shared/zen-icons/lin/close-all.svg +++ b/src/browser/themes/shared/zen-icons/lin/close-all.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/close.svg b/src/browser/themes/shared/zen-icons/lin/close.svg index 8560bd1c0..d4c541694 100644 --- a/src/browser/themes/shared/zen-icons/lin/close.svg +++ b/src/browser/themes/shared/zen-icons/lin/close.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/container-tab.svg b/src/browser/themes/shared/zen-icons/lin/container-tab.svg index 790c58e00..c9ab19f38 100644 --- a/src/browser/themes/shared/zen-icons/lin/container-tab.svg +++ b/src/browser/themes/shared/zen-icons/lin/container-tab.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/customize.svg b/src/browser/themes/shared/zen-icons/lin/customize.svg index 9b4daa6fa..ad1557a3c 100644 --- a/src/browser/themes/shared/zen-icons/lin/customize.svg +++ b/src/browser/themes/shared/zen-icons/lin/customize.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/desktop-notification-blocked.svg b/src/browser/themes/shared/zen-icons/lin/desktop-notification-blocked.svg index 4a9ed8660..6a957ec5d 100644 --- a/src/browser/themes/shared/zen-icons/lin/desktop-notification-blocked.svg +++ b/src/browser/themes/shared/zen-icons/lin/desktop-notification-blocked.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/desktop-notification.svg b/src/browser/themes/shared/zen-icons/lin/desktop-notification.svg index 2647272ed..e4b7d69ab 100644 --- a/src/browser/themes/shared/zen-icons/lin/desktop-notification.svg +++ b/src/browser/themes/shared/zen-icons/lin/desktop-notification.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/developer.svg b/src/browser/themes/shared/zen-icons/lin/developer.svg index fd575bff4..0e1b7682c 100644 --- a/src/browser/themes/shared/zen-icons/lin/developer.svg +++ b/src/browser/themes/shared/zen-icons/lin/developer.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/downloads.svg b/src/browser/themes/shared/zen-icons/lin/downloads.svg index 271fe59dc..8ad56b461 100644 --- a/src/browser/themes/shared/zen-icons/lin/downloads.svg +++ b/src/browser/themes/shared/zen-icons/lin/downloads.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/drag-indicator.svg b/src/browser/themes/shared/zen-icons/lin/drag-indicator.svg index 1fbf86104..a184de39a 100644 --- a/src/browser/themes/shared/zen-icons/lin/drag-indicator.svg +++ b/src/browser/themes/shared/zen-icons/lin/drag-indicator.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/duplicate-tab.svg b/src/browser/themes/shared/zen-icons/lin/duplicate-tab.svg index feda9b8ef..40b3ddfea 100644 --- a/src/browser/themes/shared/zen-icons/lin/duplicate-tab.svg +++ b/src/browser/themes/shared/zen-icons/lin/duplicate-tab.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/edit-copy.svg b/src/browser/themes/shared/zen-icons/lin/edit-copy.svg index 20f72247b..6cbdc5abf 100644 --- a/src/browser/themes/shared/zen-icons/lin/edit-copy.svg +++ b/src/browser/themes/shared/zen-icons/lin/edit-copy.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/edit-cut.svg b/src/browser/themes/shared/zen-icons/lin/edit-cut.svg index 601fdd3cb..388e46926 100644 --- a/src/browser/themes/shared/zen-icons/lin/edit-cut.svg +++ b/src/browser/themes/shared/zen-icons/lin/edit-cut.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/edit-delete.svg b/src/browser/themes/shared/zen-icons/lin/edit-delete.svg index a0c77b63b..fdfa752e1 100644 --- a/src/browser/themes/shared/zen-icons/lin/edit-delete.svg +++ b/src/browser/themes/shared/zen-icons/lin/edit-delete.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/edit-paste.svg b/src/browser/themes/shared/zen-icons/lin/edit-paste.svg index a2a9e1f6a..75b4b8e99 100644 --- a/src/browser/themes/shared/zen-icons/lin/edit-paste.svg +++ b/src/browser/themes/shared/zen-icons/lin/edit-paste.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/edit-redo.svg b/src/browser/themes/shared/zen-icons/lin/edit-redo.svg index f08e25b4d..806335e0c 100644 --- a/src/browser/themes/shared/zen-icons/lin/edit-redo.svg +++ b/src/browser/themes/shared/zen-icons/lin/edit-redo.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/edit-select-all.svg b/src/browser/themes/shared/zen-icons/lin/edit-select-all.svg index e59c2a0ca..0169ea041 100644 --- a/src/browser/themes/shared/zen-icons/lin/edit-select-all.svg +++ b/src/browser/themes/shared/zen-icons/lin/edit-select-all.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/edit-theme.svg b/src/browser/themes/shared/zen-icons/lin/edit-theme.svg index 97a2d2ade..d7bb565e0 100644 --- a/src/browser/themes/shared/zen-icons/lin/edit-theme.svg +++ b/src/browser/themes/shared/zen-icons/lin/edit-theme.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/edit-undo.svg b/src/browser/themes/shared/zen-icons/lin/edit-undo.svg index cf28988dd..f2d58ade0 100644 --- a/src/browser/themes/shared/zen-icons/lin/edit-undo.svg +++ b/src/browser/themes/shared/zen-icons/lin/edit-undo.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/edit.svg b/src/browser/themes/shared/zen-icons/lin/edit.svg index 052928b6b..00acd4a73 100644 --- a/src/browser/themes/shared/zen-icons/lin/edit.svg +++ b/src/browser/themes/shared/zen-icons/lin/edit.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/essential-add.svg b/src/browser/themes/shared/zen-icons/lin/essential-add.svg index 622d39314..d2345aa60 100644 --- a/src/browser/themes/shared/zen-icons/lin/essential-add.svg +++ b/src/browser/themes/shared/zen-icons/lin/essential-add.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/essential-remove.svg b/src/browser/themes/shared/zen-icons/lin/essential-remove.svg index 6675d71a1..4c537d260 100644 --- a/src/browser/themes/shared/zen-icons/lin/essential-remove.svg +++ b/src/browser/themes/shared/zen-icons/lin/essential-remove.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/expand-sidebar.svg b/src/browser/themes/shared/zen-icons/lin/expand-sidebar.svg index 04da277e5..5bc6b7533 100644 --- a/src/browser/themes/shared/zen-icons/lin/expand-sidebar.svg +++ b/src/browser/themes/shared/zen-icons/lin/expand-sidebar.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/ext-link.svg b/src/browser/themes/shared/zen-icons/lin/ext-link.svg index ec5374e08..aad946d57 100644 --- a/src/browser/themes/shared/zen-icons/lin/ext-link.svg +++ b/src/browser/themes/shared/zen-icons/lin/ext-link.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/extension-blocked.svg b/src/browser/themes/shared/zen-icons/lin/extension-blocked.svg index 8911071a4..f4d9ab6fa 100644 --- a/src/browser/themes/shared/zen-icons/lin/extension-blocked.svg +++ b/src/browser/themes/shared/zen-icons/lin/extension-blocked.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/extension.svg b/src/browser/themes/shared/zen-icons/lin/extension.svg index 7b5ebe938..52cb35692 100644 --- a/src/browser/themes/shared/zen-icons/lin/extension.svg +++ b/src/browser/themes/shared/zen-icons/lin/extension.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/folder.svg b/src/browser/themes/shared/zen-icons/lin/folder.svg index 6c5fe3631..a7a06f2ad 100644 --- a/src/browser/themes/shared/zen-icons/lin/folder.svg +++ b/src/browser/themes/shared/zen-icons/lin/folder.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/forget.svg b/src/browser/themes/shared/zen-icons/lin/forget.svg index 79f824519..679fd23f9 100644 --- a/src/browser/themes/shared/zen-icons/lin/forget.svg +++ b/src/browser/themes/shared/zen-icons/lin/forget.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/forward.svg b/src/browser/themes/shared/zen-icons/lin/forward.svg index 73619dc37..3e0786ea6 100644 --- a/src/browser/themes/shared/zen-icons/lin/forward.svg +++ b/src/browser/themes/shared/zen-icons/lin/forward.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/fullscreen-exit.svg b/src/browser/themes/shared/zen-icons/lin/fullscreen-exit.svg index 43c6448a1..193431417 100644 --- a/src/browser/themes/shared/zen-icons/lin/fullscreen-exit.svg +++ b/src/browser/themes/shared/zen-icons/lin/fullscreen-exit.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/fullscreen.svg b/src/browser/themes/shared/zen-icons/lin/fullscreen.svg index 4d0bb47b7..e7fd5a33d 100644 --- a/src/browser/themes/shared/zen-icons/lin/fullscreen.svg +++ b/src/browser/themes/shared/zen-icons/lin/fullscreen.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/geo-blocked.svg b/src/browser/themes/shared/zen-icons/lin/geo-blocked.svg index 0f803e128..c69cc2ef1 100644 --- a/src/browser/themes/shared/zen-icons/lin/geo-blocked.svg +++ b/src/browser/themes/shared/zen-icons/lin/geo-blocked.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/geo.svg b/src/browser/themes/shared/zen-icons/lin/geo.svg index 0d0c7444e..214ab0eb5 100644 --- a/src/browser/themes/shared/zen-icons/lin/geo.svg +++ b/src/browser/themes/shared/zen-icons/lin/geo.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/help.svg b/src/browser/themes/shared/zen-icons/lin/help.svg index e0fa2e29f..f2af69ec9 100644 --- a/src/browser/themes/shared/zen-icons/lin/help.svg +++ b/src/browser/themes/shared/zen-icons/lin/help.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/history.svg b/src/browser/themes/shared/zen-icons/lin/history.svg index f89b5b653..654cdca21 100644 --- a/src/browser/themes/shared/zen-icons/lin/history.svg +++ b/src/browser/themes/shared/zen-icons/lin/history.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/home.svg b/src/browser/themes/shared/zen-icons/lin/home.svg index 962b7b345..fc5c1c126 100644 --- a/src/browser/themes/shared/zen-icons/lin/home.svg +++ b/src/browser/themes/shared/zen-icons/lin/home.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/image-copy.svg b/src/browser/themes/shared/zen-icons/lin/image-copy.svg index afa7e00bb..d19cce267 100644 --- a/src/browser/themes/shared/zen-icons/lin/image-copy.svg +++ b/src/browser/themes/shared/zen-icons/lin/image-copy.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/image-open.svg b/src/browser/themes/shared/zen-icons/lin/image-open.svg index 15201ba80..6f03b3870 100644 --- a/src/browser/themes/shared/zen-icons/lin/image-open.svg +++ b/src/browser/themes/shared/zen-icons/lin/image-open.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/image-save.svg b/src/browser/themes/shared/zen-icons/lin/image-save.svg index 60372f9a5..8835026aa 100644 --- a/src/browser/themes/shared/zen-icons/lin/image-save.svg +++ b/src/browser/themes/shared/zen-icons/lin/image-save.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/info.svg b/src/browser/themes/shared/zen-icons/lin/info.svg index 67e41ad96..fc5922d2e 100644 --- a/src/browser/themes/shared/zen-icons/lin/info.svg +++ b/src/browser/themes/shared/zen-icons/lin/info.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/inspect.svg b/src/browser/themes/shared/zen-icons/lin/inspect.svg index 0ba2bd2bf..a5e4cd8d8 100644 --- a/src/browser/themes/shared/zen-icons/lin/inspect.svg +++ b/src/browser/themes/shared/zen-icons/lin/inspect.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/library.svg b/src/browser/themes/shared/zen-icons/lin/library.svg index 00c43ccdf..653a84a8e 100644 --- a/src/browser/themes/shared/zen-icons/lin/library.svg +++ b/src/browser/themes/shared/zen-icons/lin/library.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/link.svg b/src/browser/themes/shared/zen-icons/lin/link.svg index 24f91be91..16b663049 100644 --- a/src/browser/themes/shared/zen-icons/lin/link.svg +++ b/src/browser/themes/shared/zen-icons/lin/link.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/manage.svg b/src/browser/themes/shared/zen-icons/lin/manage.svg index 890b0ab0e..7613daa46 100644 --- a/src/browser/themes/shared/zen-icons/lin/manage.svg +++ b/src/browser/themes/shared/zen-icons/lin/manage.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/media-loop.svg b/src/browser/themes/shared/zen-icons/lin/media-loop.svg index 9b33cee66..d6e78c5bf 100644 --- a/src/browser/themes/shared/zen-icons/lin/media-loop.svg +++ b/src/browser/themes/shared/zen-icons/lin/media-loop.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/media-mute.svg b/src/browser/themes/shared/zen-icons/lin/media-mute.svg index c7536b3d0..e98cb1e7e 100644 --- a/src/browser/themes/shared/zen-icons/lin/media-mute.svg +++ b/src/browser/themes/shared/zen-icons/lin/media-mute.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/media-pause.svg b/src/browser/themes/shared/zen-icons/lin/media-pause.svg index 0c8282871..298a939d0 100644 --- a/src/browser/themes/shared/zen-icons/lin/media-pause.svg +++ b/src/browser/themes/shared/zen-icons/lin/media-pause.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/media-pip.svg b/src/browser/themes/shared/zen-icons/lin/media-pip.svg index 16952aa99..5366beeab 100644 --- a/src/browser/themes/shared/zen-icons/lin/media-pip.svg +++ b/src/browser/themes/shared/zen-icons/lin/media-pip.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/media-play.svg b/src/browser/themes/shared/zen-icons/lin/media-play.svg index 0cf03d66b..eec6a8e93 100644 --- a/src/browser/themes/shared/zen-icons/lin/media-play.svg +++ b/src/browser/themes/shared/zen-icons/lin/media-play.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/media-speed.svg b/src/browser/themes/shared/zen-icons/lin/media-speed.svg index 8ac325445..7a3a1017e 100644 --- a/src/browser/themes/shared/zen-icons/lin/media-speed.svg +++ b/src/browser/themes/shared/zen-icons/lin/media-speed.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/media-unmute.svg b/src/browser/themes/shared/zen-icons/lin/media-unmute.svg index f21b4c813..304ce827f 100644 --- a/src/browser/themes/shared/zen-icons/lin/media-unmute.svg +++ b/src/browser/themes/shared/zen-icons/lin/media-unmute.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/menu-bar.svg b/src/browser/themes/shared/zen-icons/lin/menu-bar.svg index 500b485af..dccd33b38 100644 --- a/src/browser/themes/shared/zen-icons/lin/menu-bar.svg +++ b/src/browser/themes/shared/zen-icons/lin/menu-bar.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/menu.svg b/src/browser/themes/shared/zen-icons/lin/menu.svg index fa8906b3f..c4df8eb08 100644 --- a/src/browser/themes/shared/zen-icons/lin/menu.svg +++ b/src/browser/themes/shared/zen-icons/lin/menu.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/microphone-blocked.svg b/src/browser/themes/shared/zen-icons/lin/microphone-blocked.svg index 60801b32a..f9865fe90 100644 --- a/src/browser/themes/shared/zen-icons/lin/microphone-blocked.svg +++ b/src/browser/themes/shared/zen-icons/lin/microphone-blocked.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/microphone.svg b/src/browser/themes/shared/zen-icons/lin/microphone.svg index abdc0c9e7..9c2ec1e6f 100644 --- a/src/browser/themes/shared/zen-icons/lin/microphone.svg +++ b/src/browser/themes/shared/zen-icons/lin/microphone.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/move-tab.svg b/src/browser/themes/shared/zen-icons/lin/move-tab.svg index 4857214fb..c57f58bd1 100644 --- a/src/browser/themes/shared/zen-icons/lin/move-tab.svg +++ b/src/browser/themes/shared/zen-icons/lin/move-tab.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/new-tab-image.svg b/src/browser/themes/shared/zen-icons/lin/new-tab-image.svg index 890f8c681..adcf6b950 100644 --- a/src/browser/themes/shared/zen-icons/lin/new-tab-image.svg +++ b/src/browser/themes/shared/zen-icons/lin/new-tab-image.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/open.svg b/src/browser/themes/shared/zen-icons/lin/open.svg index 5e1889c80..abf3a2a17 100644 --- a/src/browser/themes/shared/zen-icons/lin/open.svg +++ b/src/browser/themes/shared/zen-icons/lin/open.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/page-portrait.svg b/src/browser/themes/shared/zen-icons/lin/page-portrait.svg index 99a678428..8a84e140a 100644 --- a/src/browser/themes/shared/zen-icons/lin/page-portrait.svg +++ b/src/browser/themes/shared/zen-icons/lin/page-portrait.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/palette.svg b/src/browser/themes/shared/zen-icons/lin/palette.svg index 44c6edbf2..18a9a1cfb 100644 --- a/src/browser/themes/shared/zen-icons/lin/palette.svg +++ b/src/browser/themes/shared/zen-icons/lin/palette.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/src/browser/themes/shared/zen-icons/lin/passwords.svg b/src/browser/themes/shared/zen-icons/lin/passwords.svg index 98792083e..cb8aaf917 100644 --- a/src/browser/themes/shared/zen-icons/lin/passwords.svg +++ b/src/browser/themes/shared/zen-icons/lin/passwords.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/paste-and-go.svg b/src/browser/themes/shared/zen-icons/lin/paste-and-go.svg index 8af067def..1c1ea96a7 100644 --- a/src/browser/themes/shared/zen-icons/lin/paste-and-go.svg +++ b/src/browser/themes/shared/zen-icons/lin/paste-and-go.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/permissions.svg b/src/browser/themes/shared/zen-icons/lin/permissions.svg index 9b9976140..a6e6cdbea 100644 --- a/src/browser/themes/shared/zen-icons/lin/permissions.svg +++ b/src/browser/themes/shared/zen-icons/lin/permissions.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/persistent-storage-blocked.svg b/src/browser/themes/shared/zen-icons/lin/persistent-storage-blocked.svg index 8911071a4..f4d9ab6fa 100644 --- a/src/browser/themes/shared/zen-icons/lin/persistent-storage-blocked.svg +++ b/src/browser/themes/shared/zen-icons/lin/persistent-storage-blocked.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/persistent-storage.svg b/src/browser/themes/shared/zen-icons/lin/persistent-storage.svg index 97ac121bb..e1ad438b0 100644 --- a/src/browser/themes/shared/zen-icons/lin/persistent-storage.svg +++ b/src/browser/themes/shared/zen-icons/lin/persistent-storage.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/pin.svg b/src/browser/themes/shared/zen-icons/lin/pin.svg index 734bb8374..d95ca5f8a 100644 --- a/src/browser/themes/shared/zen-icons/lin/pin.svg +++ b/src/browser/themes/shared/zen-icons/lin/pin.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/plus.svg b/src/browser/themes/shared/zen-icons/lin/plus.svg index c426dc454..e9c44be0c 100644 --- a/src/browser/themes/shared/zen-icons/lin/plus.svg +++ b/src/browser/themes/shared/zen-icons/lin/plus.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/popup.svg b/src/browser/themes/shared/zen-icons/lin/popup.svg index 8677da7b8..5850db7fe 100644 --- a/src/browser/themes/shared/zen-icons/lin/popup.svg +++ b/src/browser/themes/shared/zen-icons/lin/popup.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/print.svg b/src/browser/themes/shared/zen-icons/lin/print.svg index 390d8d0c5..ed869a394 100644 --- a/src/browser/themes/shared/zen-icons/lin/print.svg +++ b/src/browser/themes/shared/zen-icons/lin/print.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/private-window.svg b/src/browser/themes/shared/zen-icons/lin/private-window.svg index 0c7b46a9a..3c4ee1a4b 100644 --- a/src/browser/themes/shared/zen-icons/lin/private-window.svg +++ b/src/browser/themes/shared/zen-icons/lin/private-window.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/privateBrowsing.svg b/src/browser/themes/shared/zen-icons/lin/privateBrowsing.svg index ee96e2860..d17f18965 100644 --- a/src/browser/themes/shared/zen-icons/lin/privateBrowsing.svg +++ b/src/browser/themes/shared/zen-icons/lin/privateBrowsing.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/reader-mode.svg b/src/browser/themes/shared/zen-icons/lin/reader-mode.svg index af5500748..7fa40d9ad 100644 --- a/src/browser/themes/shared/zen-icons/lin/reader-mode.svg +++ b/src/browser/themes/shared/zen-icons/lin/reader-mode.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/reload.svg b/src/browser/themes/shared/zen-icons/lin/reload.svg index 2134474d6..c67ffea49 100644 --- a/src/browser/themes/shared/zen-icons/lin/reload.svg +++ b/src/browser/themes/shared/zen-icons/lin/reload.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/report.svg b/src/browser/themes/shared/zen-icons/lin/report.svg index 3125ec5cc..b215876a9 100644 --- a/src/browser/themes/shared/zen-icons/lin/report.svg +++ b/src/browser/themes/shared/zen-icons/lin/report.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/save.svg b/src/browser/themes/shared/zen-icons/lin/save.svg index 9bac1fb43..b73e4a42e 100644 --- a/src/browser/themes/shared/zen-icons/lin/save.svg +++ b/src/browser/themes/shared/zen-icons/lin/save.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/screen-blocked.svg b/src/browser/themes/shared/zen-icons/lin/screen-blocked.svg index ffbba714a..70be3a2f5 100644 --- a/src/browser/themes/shared/zen-icons/lin/screen-blocked.svg +++ b/src/browser/themes/shared/zen-icons/lin/screen-blocked.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/screen.svg b/src/browser/themes/shared/zen-icons/lin/screen.svg index 585d8ede6..57d477a82 100644 --- a/src/browser/themes/shared/zen-icons/lin/screen.svg +++ b/src/browser/themes/shared/zen-icons/lin/screen.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/screenshot.svg b/src/browser/themes/shared/zen-icons/lin/screenshot.svg index 5f4b9619b..f2bb31372 100644 --- a/src/browser/themes/shared/zen-icons/lin/screenshot.svg +++ b/src/browser/themes/shared/zen-icons/lin/screenshot.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/search-glass.svg b/src/browser/themes/shared/zen-icons/lin/search-glass.svg index 0d5faa5ee..1e7184bcd 100644 --- a/src/browser/themes/shared/zen-icons/lin/search-glass.svg +++ b/src/browser/themes/shared/zen-icons/lin/search-glass.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/search-page.svg b/src/browser/themes/shared/zen-icons/lin/search-page.svg index da76ae067..70fb3cdc6 100644 --- a/src/browser/themes/shared/zen-icons/lin/search-page.svg +++ b/src/browser/themes/shared/zen-icons/lin/search-page.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/security-broken.svg b/src/browser/themes/shared/zen-icons/lin/security-broken.svg index 3125ec5cc..b215876a9 100644 --- a/src/browser/themes/shared/zen-icons/lin/security-broken.svg +++ b/src/browser/themes/shared/zen-icons/lin/security-broken.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/security-warning.svg b/src/browser/themes/shared/zen-icons/lin/security-warning.svg index 622bec338..d28724089 100644 --- a/src/browser/themes/shared/zen-icons/lin/security-warning.svg +++ b/src/browser/themes/shared/zen-icons/lin/security-warning.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/security.svg b/src/browser/themes/shared/zen-icons/lin/security.svg index 8ca41d326..112e1ab38 100644 --- a/src/browser/themes/shared/zen-icons/lin/security.svg +++ b/src/browser/themes/shared/zen-icons/lin/security.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/send-to-device.svg b/src/browser/themes/shared/zen-icons/lin/send-to-device.svg index 5045e0362..3fe10c0f9 100644 --- a/src/browser/themes/shared/zen-icons/lin/send-to-device.svg +++ b/src/browser/themes/shared/zen-icons/lin/send-to-device.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/settings.svg b/src/browser/themes/shared/zen-icons/lin/settings.svg index 73a363015..6dcee36e2 100644 --- a/src/browser/themes/shared/zen-icons/lin/settings.svg +++ b/src/browser/themes/shared/zen-icons/lin/settings.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/share.svg b/src/browser/themes/shared/zen-icons/lin/share.svg index 702da7aab..ac779bab1 100644 --- a/src/browser/themes/shared/zen-icons/lin/share.svg +++ b/src/browser/themes/shared/zen-icons/lin/share.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/sidebar.svg b/src/browser/themes/shared/zen-icons/lin/sidebar.svg index 754dce15a..f393b2b27 100644 --- a/src/browser/themes/shared/zen-icons/lin/sidebar.svg +++ b/src/browser/themes/shared/zen-icons/lin/sidebar.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/sidebars-right.svg b/src/browser/themes/shared/zen-icons/lin/sidebars-right.svg index 4e7f8eb29..c8ecea142 100644 --- a/src/browser/themes/shared/zen-icons/lin/sidebars-right.svg +++ b/src/browser/themes/shared/zen-icons/lin/sidebars-right.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/source-code.svg b/src/browser/themes/shared/zen-icons/lin/source-code.svg index b37c7d013..547e60268 100644 --- a/src/browser/themes/shared/zen-icons/lin/source-code.svg +++ b/src/browser/themes/shared/zen-icons/lin/source-code.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/spell-check.svg b/src/browser/themes/shared/zen-icons/lin/spell-check.svg index 0842c6b33..6d68e7315 100644 --- a/src/browser/themes/shared/zen-icons/lin/spell-check.svg +++ b/src/browser/themes/shared/zen-icons/lin/spell-check.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/split.svg b/src/browser/themes/shared/zen-icons/lin/split.svg index 8aa952db7..28b7a7601 100644 --- a/src/browser/themes/shared/zen-icons/lin/split.svg +++ b/src/browser/themes/shared/zen-icons/lin/split.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/tab-audio-blocked-small.svg b/src/browser/themes/shared/zen-icons/lin/tab-audio-blocked-small.svg index b2cf323c6..d8c3fa5dc 100644 --- a/src/browser/themes/shared/zen-icons/lin/tab-audio-blocked-small.svg +++ b/src/browser/themes/shared/zen-icons/lin/tab-audio-blocked-small.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/tab-audio-muted-small.svg b/src/browser/themes/shared/zen-icons/lin/tab-audio-muted-small.svg index 71a22dfb3..05fc6bcf9 100644 --- a/src/browser/themes/shared/zen-icons/lin/tab-audio-muted-small.svg +++ b/src/browser/themes/shared/zen-icons/lin/tab-audio-muted-small.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/tab-audio-playing-small.svg b/src/browser/themes/shared/zen-icons/lin/tab-audio-playing-small.svg index f21b4c813..304ce827f 100644 --- a/src/browser/themes/shared/zen-icons/lin/tab-audio-playing-small.svg +++ b/src/browser/themes/shared/zen-icons/lin/tab-audio-playing-small.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/tab.svg b/src/browser/themes/shared/zen-icons/lin/tab.svg index cbb67eb97..7de7e5b18 100644 --- a/src/browser/themes/shared/zen-icons/lin/tab.svg +++ b/src/browser/themes/shared/zen-icons/lin/tab.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/tool-profiler.svg b/src/browser/themes/shared/zen-icons/lin/tool-profiler.svg index fd6ae5fc2..20a44f3cd 100644 --- a/src/browser/themes/shared/zen-icons/lin/tool-profiler.svg +++ b/src/browser/themes/shared/zen-icons/lin/tool-profiler.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/tracking-protection.svg b/src/browser/themes/shared/zen-icons/lin/tracking-protection.svg index 951808edf..6e8280c93 100644 --- a/src/browser/themes/shared/zen-icons/lin/tracking-protection.svg +++ b/src/browser/themes/shared/zen-icons/lin/tracking-protection.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/translations.svg b/src/browser/themes/shared/zen-icons/lin/translations.svg index fe519338d..a8954189e 100644 --- a/src/browser/themes/shared/zen-icons/lin/translations.svg +++ b/src/browser/themes/shared/zen-icons/lin/translations.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/unpin.svg b/src/browser/themes/shared/zen-icons/lin/unpin.svg index 57473d9e0..9e7c054d1 100644 --- a/src/browser/themes/shared/zen-icons/lin/unpin.svg +++ b/src/browser/themes/shared/zen-icons/lin/unpin.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/video-open.svg b/src/browser/themes/shared/zen-icons/lin/video-open.svg index d34336b6b..944ece3a3 100644 --- a/src/browser/themes/shared/zen-icons/lin/video-open.svg +++ b/src/browser/themes/shared/zen-icons/lin/video-open.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/video-save.svg b/src/browser/themes/shared/zen-icons/lin/video-save.svg index 09ddcaa1f..28e31b140 100644 --- a/src/browser/themes/shared/zen-icons/lin/video-save.svg +++ b/src/browser/themes/shared/zen-icons/lin/video-save.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/window.svg b/src/browser/themes/shared/zen-icons/lin/window.svg index 890f8c681..adcf6b950 100644 --- a/src/browser/themes/shared/zen-icons/lin/window.svg +++ b/src/browser/themes/shared/zen-icons/lin/window.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/xr-blocked.svg b/src/browser/themes/shared/zen-icons/lin/xr-blocked.svg index 266caf8b0..e5bd237e0 100644 --- a/src/browser/themes/shared/zen-icons/lin/xr-blocked.svg +++ b/src/browser/themes/shared/zen-icons/lin/xr-blocked.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/xr.svg b/src/browser/themes/shared/zen-icons/lin/xr.svg index 743a3fc36..fd6465b54 100644 --- a/src/browser/themes/shared/zen-icons/lin/xr.svg +++ b/src/browser/themes/shared/zen-icons/lin/xr.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/zoom-control.svg b/src/browser/themes/shared/zen-icons/lin/zoom-control.svg index 91d85daf6..0a3e42ef5 100644 --- a/src/browser/themes/shared/zen-icons/lin/zoom-control.svg +++ b/src/browser/themes/shared/zen-icons/lin/zoom-control.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/zoom-out.svg b/src/browser/themes/shared/zen-icons/lin/zoom-out.svg index 57473d9e0..9e7c054d1 100644 --- a/src/browser/themes/shared/zen-icons/lin/zoom-out.svg +++ b/src/browser/themes/shared/zen-icons/lin/zoom-out.svg @@ -1 +1 @@ - + From ddb0a65957379c90e9fe5d71493d14c391e1c962 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Thu, 6 Mar 2025 12:55:34 +0100 Subject: [PATCH 042/127] Refactor Zen components: update CSS variable for toolbar button fill, improve tab unloading logic, and enhance tab icon URLs --- src/browser/base/content/zen-styles/zen-theme.css | 2 +- src/browser/base/zen-components/ZenTabUnloader.mjs | 4 ++-- src/browser/base/zen-components/ZenWelcome.mjs | 6 +++--- src/browser/base/zen-components/ZenWorkspaces.mjs | 2 -- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-theme.css b/src/browser/base/content/zen-styles/zen-theme.css index 933260e21..8f12e26b9 100644 --- a/src/browser/base/content/zen-styles/zen-theme.css +++ b/src/browser/base/content/zen-styles/zen-theme.css @@ -79,7 +79,7 @@ --focus-outline-color: var(--button-bgcolor) !important; --toolbarbutton-icon-fill-attention: var(--zen-primary-color) !important; - --toolbarbutton-icon-fill: light-dark(rgba(57, 57, 58, .6), rgba(251, 251, 254, .6)) !important; + --toolbarbutton-icon-fill: light-dark(rgba(57, 57, 58, 0.6), rgba(251, 251, 254, 0.6)) !important; --button-primary-bgcolor: var(--in-content-primary-button-background) !important; --button-primary-hover-bgcolor: var(--in-content-primary-button-background-hover) !important; diff --git a/src/browser/base/zen-components/ZenTabUnloader.mjs b/src/browser/base/zen-components/ZenTabUnloader.mjs index f305ad0cb..64c407fac 100644 --- a/src/browser/base/zen-components/ZenTabUnloader.mjs +++ b/src/browser/base/zen-components/ZenTabUnloader.mjs @@ -274,8 +274,8 @@ (tab.pictureinpicture && !ignoreTimestamp) || (tab.soundPlaying && !ignoreTimestamp) || (tab.zenIgnoreUnload && !ignoreTimestamp) || - (excludedUrls.some((url) => url.test(tab.linkedBrowser?.currentURI.spec)) - && tab.linkedBrowser?.currentURI.spec !== 'about:blank') + (excludedUrls.some((url) => url.test(tab.linkedBrowser?.currentURI.spec)) && + tab.linkedBrowser?.currentURI.spec !== 'about:blank') ) { return false; } diff --git a/src/browser/base/zen-components/ZenWelcome.mjs b/src/browser/base/zen-components/ZenWelcome.mjs index 32bd7f6e1..de91b7e01 100644 --- a/src/browser/base/zen-components/ZenWelcome.mjs +++ b/src/browser/base/zen-components/ZenWelcome.mjs @@ -340,7 +340,7 @@ - + @@ -370,12 +370,12 @@ - + - + diff --git a/src/browser/base/zen-components/ZenWorkspaces.mjs b/src/browser/base/zen-components/ZenWorkspaces.mjs index e14d91a9e..7e8ca9969 100644 --- a/src/browser/base/zen-components/ZenWorkspaces.mjs +++ b/src/browser/base/zen-components/ZenWorkspaces.mjs @@ -614,8 +614,6 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { if (currentTab.pinned) { this.selectEmptyTab(); try { - console.log(currentTab) - console.log(currentTab.linkedBrowser?.currentURI.spec) gZenTabUnloader.explicitUnloadTabs([currentTab]); } catch (e) { console.error('ZenWorkspaces: Error unloading tab', e); From d698c51ce0910754635ef822741d6c190fd971c6 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Thu, 6 Mar 2025 13:36:43 +0100 Subject: [PATCH 043/127] Fix tab container assignment to retain existing vertical pinned tabs --- src/browser/base/zen-components/ZenWorkspaces.mjs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/browser/base/zen-components/ZenWorkspaces.mjs b/src/browser/base/zen-components/ZenWorkspaces.mjs index 7e8ca9969..6a63c1372 100644 --- a/src/browser/base/zen-components/ZenWorkspaces.mjs +++ b/src/browser/base/zen-components/ZenWorkspaces.mjs @@ -1518,8 +1518,9 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { const workspaces = await this._workspaces(); // Refresh tab cache - gBrowser.verticalPinnedTabsContainer = this.pinnedTabsContainer; - gBrowser.tabContainer.verticalPinnedTabsContainer = this.pinnedTabsContainer; + gBrowser.verticalPinnedTabsContainer = this.pinnedTabsContainer || gBrowser.verticalPinnedTabsContainer; + gBrowser.tabContainer.verticalPinnedTabsContainer = + this.pinnedTabsContainer || gBrowser.tabContainer.verticalPinnedTabsContainer; // Move empty tab to the new workspace this._moveEmptyTabToWorkspace(window.uuid); From 671a76bf869e81458385aa61462063f87b3805f1 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Thu, 6 Mar 2025 14:58:35 +0100 Subject: [PATCH 044/127] Refactor workspace settings and improve tab management; remove individual pinned tabs preference, update bootstrap command, and enhance tab removal logic for non-existent workspaces. --- l10n | 2 +- package.json | 2 +- src/browser/app/profile/zen-browser.js | 1 - .../base/content/zen-styles/zen-decks.css | 2 +- .../base/zen-components/ZenViewSplitter.mjs | 7 +++-- .../base/zen-components/ZenWorkspaces.mjs | 28 +++++++++++++++++-- .../components/preferences/zen-settings.js | 5 ---- .../preferences/zenTabsManagement.inc.xhtml | 3 -- 8 files changed, 32 insertions(+), 18 deletions(-) diff --git a/l10n b/l10n index b109ad083..1a15769b8 160000 --- a/l10n +++ b/l10n @@ -1 +1 @@ -Subproject commit b109ad0835e08402fe76f8765789966139ebb432 +Subproject commit 1a15769b8d5add458f7e5716c337e471687f3f25 diff --git a/package.json b/package.json index e87dd6543..91d2afd4c 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "export": "surfer export", "init": "npm run download && npm run bootstrap && npm run import", "download": "surfer download", - "bootstrap": "surfer bootstrap && surfer bootstrap", + "bootstrap": "surfer bootstrap", "package": "surfer package", "update-ff": "python3 scripts/update_ff.py", "update-ff:raw": "surfer update", diff --git a/src/browser/app/profile/zen-browser.js b/src/browser/app/profile/zen-browser.js index b9ec6fd81..102fc4a3f 100644 --- a/src/browser/app/profile/zen-browser.js +++ b/src/browser/app/profile/zen-browser.js @@ -198,7 +198,6 @@ pref('zen.startup.smooth-scroll-in-tabs', true); pref('zen.workspaces.disabled_for_testing', false); pref('zen.workspaces.hide-deactivated-workspaces', false); pref('zen.workspaces.hide-default-container-indicator', true); -pref('zen.workspaces.individual-pinned-tabs', true); pref('zen.workspaces.show-icon-strip', true); pref('zen.workspaces.force-container-workspace', false); pref('zen.workspaces.open-new-tab-if-last-unpinned-tab-is-closed', false); diff --git a/src/browser/base/content/zen-styles/zen-decks.css b/src/browser/base/content/zen-styles/zen-decks.css index 80e26070d..c89cc0727 100644 --- a/src/browser/base/content/zen-styles/zen-decks.css +++ b/src/browser/base/content/zen-styles/zen-decks.css @@ -247,7 +247,7 @@ cursor: pointer; appearance: none; outline: none; - color: var(--button-primary-color); + color: var(--button-primary-bgcolor); border-top-left-radius: 0; border-top-right-radius: 0; diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index b327fcc17..024a69e58 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -51,7 +51,7 @@ class SplitNode extends SplitLeafNode { addChild(child) { child.parent = this; - this._children.push(child); + this._children.unshift(child); } } @@ -1511,7 +1511,8 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { } const containerRect = this.fakeBrowser.getBoundingClientRect(); - const dropTarget = document.elementFromPoint((containerRect.left + containerRect.width) * 1.5, event.clientY); + const padding = Services.prefs.getIntPref('zen.theme.content-element-separation', 0); + const dropTarget = document.elementFromPoint(containerRect.left + containerRect.width + padding + 5, event.clientY); const browser = dropTarget?.closest('browser'); if (!browser) { @@ -1531,7 +1532,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { // Calculate which side of the target browser the drop occurred // const browserRect = browser.getBoundingClientRect(); // const hoverSide = this.calculateHoverSide(event.clientX, event.clientY, browserRect); - const hoverSide = 'right'; + const hoverSide = 'left'; if (droppedOnTab.splitView) { // Add to existing split view diff --git a/src/browser/base/zen-components/ZenWorkspaces.mjs b/src/browser/base/zen-components/ZenWorkspaces.mjs index 6a63c1372..cc558e72e 100644 --- a/src/browser/base/zen-components/ZenWorkspaces.mjs +++ b/src/browser/base/zen-components/ZenWorkspaces.mjs @@ -605,6 +605,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { this._selectStartPage(); this._fixTabPositions(); this._resolveInitialized(); + this._clearAnyZombieTabs(); // Dont call with await } } @@ -652,6 +653,26 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { return !window.toolbar.visible || Services.prefs.getBoolPref('browser.tabs.closeWindowWithLastTab'); } + async _clearAnyZombieTabs() { + const tabs = this.allStoredTabs; + const workspaces = await this._workspaces(); + for (let tab of tabs) { + const workspaceID = tab.getAttribute('zen-workspace-id'); + if ( + workspaceID && + !tab.hasAttribute('zen-essential') && + !workspaces.workspaces.find((workspace) => workspace.uuid === workspaceID) + ) { + // Remove any tabs where their workspace doesn't exist anymore + gBrowser.removeTab(tab, { + animate: false, + skipSessionStore: true, + closeWindowWithLastTab: false, + }); + } + } + } + handleTabBeforeClose(tab) { if (!this.workspaceEnabled || this.__contextIsDelete || this._removedByStartupPage) { return null; @@ -1382,10 +1403,10 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { } _deleteAllTabsInWorkspace(workspaceID) { - for (let tab of gBrowser.tabs) { + for (let tab of this.allStoredTabs) { if (tab.getAttribute('zen-workspace-id') === workspaceID) { gBrowser.removeTab(tab, { - animate: true, + animate: false, skipSessionStore: true, closeWindowWithLastTab: false, }); @@ -1508,12 +1529,12 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { const previousWorkspace = await this.getActiveWorkspace(); alwaysChange = alwaysChange || onInit; + this.activeWorkspace = window.uuid; if (previousWorkspace && previousWorkspace.uuid === window.uuid && !alwaysChange) { this._cancelSwipeAnimation(); return; } - this.activeWorkspace = window.uuid; const containerId = window.containerTabId?.toString(); const workspaces = await this._workspaces(); @@ -1995,6 +2016,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { // Switch workspace if needed if (workspaceID && workspaceID !== activeWorkspace.uuid && parent.ZenWorkspaces._hasInitializedTabsStrip) { + const workspaces = await parent.ZenWorkspaces._workspaces(); await parent.ZenWorkspaces.changeWorkspace({ uuid: workspaceID }); } } diff --git a/src/browser/components/preferences/zen-settings.js b/src/browser/components/preferences/zen-settings.js index 7b8e3e10b..19892d0fa 100644 --- a/src/browser/components/preferences/zen-settings.js +++ b/src/browser/components/preferences/zen-settings.js @@ -944,11 +944,6 @@ Preferences.addAll([ type: 'bool', default: true, }, - { - id: 'zen.workspaces.individual-pinned-tabs', - type: 'bool', - default: true, - }, { id: 'zen.workspaces.show-icon-strip', type: 'bool', diff --git a/src/browser/components/preferences/zenTabsManagement.inc.xhtml b/src/browser/components/preferences/zenTabsManagement.inc.xhtml index 490ffef07..458e05120 100644 --- a/src/browser/components/preferences/zenTabsManagement.inc.xhtml +++ b/src/browser/components/preferences/zenTabsManagement.inc.xhtml @@ -20,9 +20,6 @@ - From b93faff7719e1fdd501f7cef4889083deab57b4c Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Thu, 6 Mar 2025 15:25:06 +0100 Subject: [PATCH 045/127] Fix CSS width calculation for expanded sidebar and correct typo in opacity removal; ensure proper tab icon updates on pinning. --- src/browser/base/content/zen-styles/zen-compact-mode.css | 5 ++++- src/browser/base/zen-components/ZenCompactMode.mjs | 2 +- src/browser/base/zen-components/ZenPinnedTabManager.mjs | 3 +-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-compact-mode.css b/src/browser/base/content/zen-styles/zen-compact-mode.css index bb0f98601..56f491efe 100644 --- a/src/browser/base/content/zen-styles/zen-compact-mode.css +++ b/src/browser/base/content/zen-styles/zen-compact-mode.css @@ -103,7 +103,10 @@ position: relative; background: var(--zen-dialog-background); border: 1px solid var(--zen-colors-border-contrast); - width: calc(100% - var(--zen-toolbox-padding)); + /* times 4 because we have the inner padding and the outter padding to consider */ + :root[zen-sidebar-expanded='true'] & { + width: calc(100% + var(--zen-toolbox-padding)); + } :root[zen-single-toolbar='true'] { padding-top: 0 !important; diff --git a/src/browser/base/zen-components/ZenCompactMode.mjs b/src/browser/base/zen-components/ZenCompactMode.mjs index 2bbade9ed..e95c31ab4 100644 --- a/src/browser/base/zen-components/ZenCompactMode.mjs +++ b/src/browser/base/zen-components/ZenCompactMode.mjs @@ -202,7 +202,7 @@ var gZenCompactModeManager = { this._animating = false; this.sidebar.style.removeProperty('visibility'); this.sidebar.style.removeProperty('transition'); - thhis.sidebar.style.removeProperty('opacity'); + this.sidebar.style.removeProperty('opacity'); }, 300); }); }); diff --git a/src/browser/base/zen-components/ZenPinnedTabManager.mjs b/src/browser/base/zen-components/ZenPinnedTabManager.mjs index 35f937ac2..a7c91903e 100644 --- a/src/browser/base/zen-components/ZenPinnedTabManager.mjs +++ b/src/browser/base/zen-components/ZenPinnedTabManager.mjs @@ -82,7 +82,6 @@ } onTabIconChanged(tab, url = null) { - const iconUrl = url ?? tab.iconImage.src; if (tab.hasAttribute('zen-essential') && this._pinsCache) { const pin = this._pinsCache.find((pin) => pin.uuid === tab.getAttribute('zen-pin-id')); if (pin) { @@ -631,8 +630,8 @@ } else { gBrowser.pinTab(tab); } - this.onTabIconChanged(tab); this._onTabMove(tab); + this.onTabIconChanged(tab); } gZenUIManager.updateTabsToolbar(); } From 8ed5b50c3dcabfa1d188009b041d93799aa03282 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Thu, 6 Mar 2025 16:06:15 +0100 Subject: [PATCH 046/127] Fix tab label handling and improve pinned tab state management; ensure static labels are correctly set and cached. --- .../zen-components/ZenPinnedTabManager.mjs | 23 ++++++- .../base/zen-components/ZenTabUnloader.mjs | 2 +- .../sessionstore/SessionStore-sys-mjs.patch | 13 ++-- .../sessionstore/TabState-sys-mjs.patch | 5 +- .../tabbrowser/content/tabbrowser-js.patch | 62 ++++++++++--------- 5 files changed, 66 insertions(+), 39 deletions(-) diff --git a/src/browser/base/zen-components/ZenPinnedTabManager.mjs b/src/browser/base/zen-components/ZenPinnedTabManager.mjs index a7c91903e..66d84d6f3 100644 --- a/src/browser/base/zen-components/ZenPinnedTabManager.mjs +++ b/src/browser/base/zen-components/ZenPinnedTabManager.mjs @@ -213,8 +213,9 @@ continue; } - if (pin.title && pin.editedTitle) { - gBrowser._setTabLabel(tab, pin.title); + if (pin.title && (pin.editedTitle || tab.hasAttribute('zen-has-static-label'))) { + tab.removeAttribute('zen-has-static-label'); // So we can set it again + gBrowser._setTabLabel(tab, pin.title, { beforeTabOpen: true }); tab.setAttribute('zen-has-static-label', 'true'); } } @@ -341,7 +342,7 @@ tab.position = tab._tPos; for (let otherTab of gBrowser.tabs) { - if (otherTab.pinned) { + if (otherTab.pinned && otherTab.getAttribute('zen-pin-id') !== tab.getAttribute('zen-pin-id')) { const actualPin = this._pinsCache.find((pin) => pin.uuid === otherTab.getAttribute('zen-pin-id')); if (!actualPin) { continue; @@ -358,6 +359,13 @@ } actualPin.position = tab.position; actualPin.isEssential = tab.hasAttribute('zen-essential'); + + // There was a bug where the title and hasStaticLabel attribute were not being set + // This is a workaround to fix that + if (tab.hasAttribute('zen-has-static-label')) { + actualPin.editedTitle = true; + actualPin.title = tab.label; + } await this.savePin(actualPin); } @@ -846,6 +854,15 @@ // update the label for the same pin across all windows for (const browser of browsers) { const tabs = browser.gBrowser.tabs; + // Fix pinned cache for the browser + const browserCache = browser.gZenPinnedTabManager?._pinsCache; + if (browserCache) { + const pin = browserCache.find((pin) => pin.uuid === uuid); + if (pin) { + pin.title = newTitle; + pin.editedTitle = isEdited; + } + } for (let i = 0; i < tabs.length; i++) { const tabToEdit = tabs[i]; if (tabToEdit.getAttribute('zen-pin-id') === uuid && tabToEdit !== tab) { diff --git a/src/browser/base/zen-components/ZenTabUnloader.mjs b/src/browser/base/zen-components/ZenTabUnloader.mjs index 64c407fac..01219d57a 100644 --- a/src/browser/base/zen-components/ZenTabUnloader.mjs +++ b/src/browser/base/zen-components/ZenTabUnloader.mjs @@ -264,7 +264,7 @@ (tab.pinned && !ignoreTimestamp) || tab.selected || (tab.multiselected && !ignoreTimestamp) || - tab.hasAttribute('busy') || + (tab.hasAttribute('busy') && !ignoreTimestamp) || tab.hasAttribute('pending') || !tab.linkedPanel || tab.splitView || diff --git a/src/browser/components/sessionstore/SessionStore-sys-mjs.patch b/src/browser/components/sessionstore/SessionStore-sys-mjs.patch index 632ca6803..de0a9684b 100644 --- a/src/browser/components/sessionstore/SessionStore-sys-mjs.patch +++ b/src/browser/components/sessionstore/SessionStore-sys-mjs.patch @@ -1,8 +1,8 @@ diff --git a/browser/components/sessionstore/SessionStore.sys.mjs b/browser/components/sessionstore/SessionStore.sys.mjs -index 908743177d9f95e2e6549c689e7a493ca8668701..181c4819b052e444e56e75f1cb40b4bc299569fb 100644 +index f814772114948f87cbb3c3a7231c95ea1f68d776..296cce151690b31a6e136dd5046a2697fb46fe45 100644 --- a/browser/components/sessionstore/SessionStore.sys.mjs +++ b/browser/components/sessionstore/SessionStore.sys.mjs -@@ -3848,6 +3848,7 @@ var SessionStoreInternal = { +@@ -3881,6 +3881,7 @@ var SessionStoreInternal = { aWindow.gBrowser.selectedTab = newTab; } @@ -10,7 +10,7 @@ index 908743177d9f95e2e6549c689e7a493ca8668701..181c4819b052e444e56e75f1cb40b4bc // Restore the state into the new tab. this.restoreTab(newTab, tabState, { restoreImmediately: aRestoreImmediately, -@@ -5315,14 +5316,14 @@ var SessionStoreInternal = { +@@ -5355,14 +5356,14 @@ var SessionStoreInternal = { } let tabbrowser = aWindow.gBrowser; @@ -27,7 +27,7 @@ index 908743177d9f95e2e6549c689e7a493ca8668701..181c4819b052e444e56e75f1cb40b4bc continue; } let tabData = lazy.TabState.collect(tab, TAB_CUSTOM_VALUES.get(tab)); -@@ -6042,6 +6043,15 @@ var SessionStoreInternal = { +@@ -6086,6 +6087,18 @@ var SessionStoreInternal = { // Most of tabData has been restored, now continue with restoring // attributes that may trigger external events. @@ -35,7 +35,10 @@ index 908743177d9f95e2e6549c689e7a493ca8668701..181c4819b052e444e56e75f1cb40b4bc + tab.setAttribute("zen-essential", "true"); + } + if (tabData.zenIsEmpty) { -+ tab.setAttribute("zen-empty-tab", "true"); ++ tab.setAttribute("zen-empty-tab", "true"); ++ } ++ if (tabData.zenHasStaticLabel) { ++ tab.setAttribute("zen-has-static-label", "true"); + } + if (tabData.zenPinnedId) { + tab.setAttribute("zen-pin-id", tabData.zenPinnedId); diff --git a/src/browser/components/sessionstore/TabState-sys-mjs.patch b/src/browser/components/sessionstore/TabState-sys-mjs.patch index 2fc82f1af..7b4d912d8 100644 --- a/src/browser/components/sessionstore/TabState-sys-mjs.patch +++ b/src/browser/components/sessionstore/TabState-sys-mjs.patch @@ -1,8 +1,8 @@ diff --git a/browser/components/sessionstore/TabState.sys.mjs b/browser/components/sessionstore/TabState.sys.mjs -index 8f7ed557e6aa61e7e16ed4a8d785ad5fe651b3d8..8b0781488e8f250666f1d542e3aa0cb34e018f24 100644 +index 8f7ed557e6aa61e7e16ed4a8d785ad5fe651b3d8..4c9f17408b912a2c51ebc1a670062203bf4994f3 100644 --- a/browser/components/sessionstore/TabState.sys.mjs +++ b/browser/components/sessionstore/TabState.sys.mjs -@@ -80,10 +80,18 @@ class _TabState { +@@ -80,10 +80,19 @@ class _TabState { tabData.muteReason = tab.muteReason; } @@ -18,6 +18,7 @@ index 8f7ed557e6aa61e7e16ed4a8d785ad5fe651b3d8..8b0781488e8f250666f1d542e3aa0cb3 + tabData.zenPinnedEntry = tab.getAttribute("zen-pinned-entry"); + tabData.zenPinnedIcon = tab.getAttribute("zen-pinned-icon"); + tabData.zenIsEmpty = tab.hasAttribute("zen-empty-tab"); ++ tabData.zenHasStaticLabel = tab.hasAttribute("zen-has-static-label"); + tabData.searchMode = tab.ownerGlobal.gURLBar.getSearchMode(browser, true); diff --git a/src/browser/components/tabbrowser/content/tabbrowser-js.patch b/src/browser/components/tabbrowser/content/tabbrowser-js.patch index 96cbe160e..1ccc22b36 100644 --- a/src/browser/components/tabbrowser/content/tabbrowser-js.patch +++ b/src/browser/components/tabbrowser/content/tabbrowser-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js -index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe122b7900f1 100644 +index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867792a2220 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js @@ -412,11 +412,50 @@ @@ -276,7 +276,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 }); } -@@ -3367,6 +3447,24 @@ +@@ -3367,6 +3447,27 @@ ) { tabWasReused = true; tab = this.selectedTab; @@ -286,6 +286,9 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 + if (tabData.zenIsEmpty) { + tab.setAttribute("zen-empty-tab", "true"); + } ++ if (tabData.zenHasStaticLabel) { ++ tab.setAttribute("zen-has-static-label", "true"); ++ } + if (tabData.zenPinnedId) { + tab.setAttribute("zen-pin-id", tabData.zenPinnedId); + } @@ -301,7 +304,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 if (!tabData.pinned) { this.unpinTab(tab); } else { -@@ -3380,6 +3478,7 @@ +@@ -3380,6 +3481,7 @@ restoreTabsLazily && !select && !tabData.pinned; let url = "about:blank"; @@ -309,7 +312,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 if (tabData.entries?.length) { let activeIndex = (tabData.index || tabData.entries.length) - 1; // Ensure the index is in bounds. -@@ -3415,7 +3514,24 @@ +@@ -3415,7 +3517,27 @@ skipLoad: true, preferredRemoteType, }); @@ -323,6 +326,9 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 + if (tabData.zenIsEmpty) { + tab.setAttribute("zen-empty-tab", "true"); + } ++ if (tabData.zenHasStaticLabel) { ++ tab.setAttribute("zen-has-static-label", "true"); ++ } + if (tabData.zenEssential) { + tab.setAttribute("zen-essential", "true"); + } @@ -335,7 +341,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 if (select) { tabToSelect = tab; } -@@ -3428,8 +3544,8 @@ +@@ -3428,8 +3550,8 @@ // inserted in the DOM. If the tab is not yet in the DOM, // just insert it in the right place from the start. if (!tab.parentNode) { @@ -346,7 +352,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 tab.toggleAttribute("pinned", true); this.tabContainer._invalidateCachedTabs(); // Then ensure all the tab open/pinning information is sent. -@@ -3693,7 +3809,7 @@ +@@ -3693,7 +3815,7 @@ // Ensure we have an index if one was not provided. if (typeof index != "number") { // Move the new tab after another tab if needed, to the end otherwise. @@ -355,7 +361,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 if ( !bulkOrderedOpen && ((openerTab && -@@ -3736,18 +3852,18 @@ +@@ -3736,18 +3858,18 @@ // Ensure index is within bounds. if (tab.pinned) { @@ -378,7 +384,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 if (tabAfter && tabAfter.group == tabGroup) { // Place at the front of, or between tabs in, the same tab group this.tabContainer.insertBefore(tab, tabAfter); -@@ -4059,6 +4175,9 @@ +@@ -4059,6 +4181,9 @@ return; } @@ -388,7 +394,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 this.removeTabs(selectedTabs); } -@@ -4391,6 +4510,7 @@ +@@ -4391,6 +4516,7 @@ skipSessionStore, } = {} ) { @@ -396,7 +402,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 if (UserInteraction.running("browser.tabs.opening", window)) { UserInteraction.finish("browser.tabs.opening", window); } -@@ -4407,6 +4527,12 @@ +@@ -4407,6 +4533,12 @@ TelemetryStopwatch.start("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab); } @@ -409,7 +415,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 // Handle requests for synchronously removing an already // asynchronously closing tab. if (!animate && aTab.closing) { -@@ -4421,7 +4547,9 @@ +@@ -4421,7 +4553,9 @@ // frame created for it (for example, by updating the visually selected // state). let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width; @@ -420,7 +426,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 if ( !this._beginRemoveTab(aTab, { closeWindowFastpath: true, -@@ -4435,7 +4563,6 @@ +@@ -4435,7 +4569,6 @@ TelemetryStopwatch.cancel("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab); return; } @@ -428,7 +434,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 let lockTabSizing = !this.tabContainer.verticalMode && !aTab.pinned && -@@ -4574,14 +4701,14 @@ +@@ -4574,14 +4707,14 @@ !!this.tabsInCollapsedTabGroups.length; if ( aTab.visible && @@ -445,7 +451,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 if (closeWindow) { // We've already called beforeunload on all the relevant tabs if we get here, -@@ -4605,6 +4732,7 @@ +@@ -4605,6 +4738,7 @@ newTab = true; } @@ -453,7 +459,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 aTab._endRemoveArgs = [closeWindow, newTab]; // swapBrowsersAndCloseOther will take care of closing the window without animation. -@@ -4645,9 +4773,7 @@ +@@ -4645,9 +4779,7 @@ aTab._mouseleave(); if (newTab) { @@ -464,7 +470,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 } else { TabBarVisibility.update(); } -@@ -4776,6 +4902,8 @@ +@@ -4776,6 +4908,8 @@ this.tabs[i]._tPos = i; } @@ -473,7 +479,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 if (!this._windowIsClosing) { if (wasPinned) { this.tabContainer._positionPinnedTabs(); -@@ -4994,7 +5122,7 @@ +@@ -4994,7 +5128,7 @@ !excludeTabs.has(aTab.owner) && Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose") ) { @@ -482,7 +488,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 } // Try to find a remaining tab that comes after the given tab -@@ -5016,7 +5144,7 @@ +@@ -5016,7 +5150,7 @@ } if (tab) { @@ -491,7 +497,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 } // If no qualifying visible tab was found, see if there is a tab in -@@ -5434,10 +5562,10 @@ +@@ -5434,10 +5568,10 @@ SessionStore.deleteCustomTabValue(aTab, "hiddenBy"); } @@ -504,7 +510,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 aTab.selected || aTab.closing || // Tabs that are sharing the screen, microphone or camera cannot be hidden. -@@ -5675,7 +5803,7 @@ +@@ -5675,7 +5809,7 @@ // Don't allow mixing pinned and unpinned tabs. if (aTab.pinned) { @@ -513,7 +519,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 } else { aIndex = Math.max(aIndex, this.pinnedTabCount); } -@@ -5684,11 +5812,18 @@ +@@ -5684,11 +5818,18 @@ } this._handleTabMove(aTab, () => { @@ -535,7 +541,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 neighbor.after(aTab); } else { this.tabContainer.insertBefore(aTab, neighbor); -@@ -5697,7 +5832,7 @@ +@@ -5697,7 +5838,7 @@ } moveTabToGroup(aTab, aGroup) { @@ -544,7 +550,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 return; } if (aTab.group && aTab.group.id === aGroup.id) { -@@ -5721,6 +5856,10 @@ +@@ -5721,6 +5862,10 @@ moveActionCallback(); @@ -555,7 +561,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 // Clear tabs cache after moving nodes because the order of tabs may have // changed. this.tabContainer._invalidateCachedTabs(); -@@ -5771,7 +5910,7 @@ +@@ -5771,7 +5916,7 @@ createLazyBrowser, }; @@ -564,7 +570,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 if (aIndex < numPinned || (aTab.pinned && aIndex == numPinned)) { params.pinned = true; } -@@ -7415,6 +7554,7 @@ +@@ -7415,6 +7560,7 @@ aWebProgress.isTopLevel ) { this.mTab.setAttribute("busy", "true"); @@ -572,7 +578,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 gBrowser._tabAttrModified(this.mTab, ["busy"]); this.mTab._notselectedsinceload = !this.mTab.selected; } -@@ -8381,7 +8521,7 @@ var TabContextMenu = { +@@ -8381,7 +8527,7 @@ var TabContextMenu = { ); contextUnpinSelectedTabs.hidden = !this.contextTab.pinned || !multiselectionContext; @@ -581,7 +587,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 // Move Tab items let contextMoveTabOptions = document.getElementById( "context_moveTabOptions" -@@ -8414,7 +8554,7 @@ var TabContextMenu = { +@@ -8414,7 +8560,7 @@ var TabContextMenu = { let contextMoveTabToStart = document.getElementById("context_moveToStart"); let isFirstTab = tabsToMove[0] == visibleTabs[0] || @@ -590,7 +596,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f3cb04e9034d24752bdf6911e647fe12 contextMoveTabToStart.disabled = isFirstTab && allSelectedTabsAdjacent; document.getElementById("context_openTabInWindow").disabled = -@@ -8647,6 +8787,7 @@ var TabContextMenu = { +@@ -8647,6 +8793,7 @@ var TabContextMenu = { if (this.contextTab.multiselected) { gBrowser.removeMultiSelectedTabs(); } else { From 391cb84117cbd1adf967b576be82da38095e0770 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Thu, 6 Mar 2025 16:10:25 +0100 Subject: [PATCH 047/127] Fix tab position calculation to ensure new tabs are inserted correctly after the current tab --- src/browser/base/zen-components/ZenGlanceManager.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/base/zen-components/ZenGlanceManager.mjs b/src/browser/base/zen-components/ZenGlanceManager.mjs index f8368dbed..5f3b6979b 100644 --- a/src/browser/base/zen-components/ZenGlanceManager.mjs +++ b/src/browser/base/zen-components/ZenGlanceManager.mjs @@ -79,7 +79,7 @@ skipBackgroundNotify: true, insertTab: true, skipLoad: false, - index: this.getTabPosition(currentTab), + index: this.getTabPosition(currentTab) + 1, }; currentTab._selected = true; const newUUID = gZenUIManager.generateUuidv4(); From b9eb13f033a79703960b6e0d66b98f8e1ad879c4 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Thu, 6 Mar 2025 20:39:34 +0100 Subject: [PATCH 048/127] Fix sidebar width calculations and improve compact mode styling; ensure accurate width properties are set and remove unnecessary transformations. --- .../base/content/zen-styles/zen-compact-mode.css | 12 +++++++++--- .../base/content/zen-styles/zen-sidebar-panels.css | 5 ----- src/browser/base/zen-components/ZenCompactMode.mjs | 13 ++++++++++++- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-compact-mode.css b/src/browser/base/content/zen-styles/zen-compact-mode.css index 56f491efe..3fede326d 100644 --- a/src/browser/base/content/zen-styles/zen-compact-mode.css +++ b/src/browser/base/content/zen-styles/zen-compact-mode.css @@ -69,7 +69,7 @@ } &:not([zen-right-side='true']) #navigator-toolbox { - left: calc(-1 * var(--zen-sidebar-width) + 1px); + left: calc(-1 * var(--actual-zen-sidebar-width) + 1px); } /* When we have multiple toolbars and the top-toolbar is NOT being hidden, @@ -86,7 +86,7 @@ --zen-compact-float: calc(var(--zen-element-separation) + 1px); &:not([animate='true']) { - right: calc(-1 * var(--zen-sidebar-width) + 1px); + right: calc(-1 * var(--actual-zen-sidebar-width) + 1px); } } @@ -105,7 +105,13 @@ border: 1px solid var(--zen-colors-border-contrast); /* times 4 because we have the inner padding and the outter padding to consider */ :root[zen-sidebar-expanded='true'] & { - width: calc(100% + var(--zen-toolbox-padding)); + &[has-animated-padding='true'] { + width: calc(var(--zen-sidebar-width) + var(--zen-toolbox-padding)); + } + + &:not([has-animated-padding='true']) { + width: calc(var(--zen-sidebar-width) - var(--zen-toolbox-padding)); + } } :root[zen-single-toolbar='true'] { diff --git a/src/browser/base/content/zen-styles/zen-sidebar-panels.css b/src/browser/base/content/zen-styles/zen-sidebar-panels.css index a22fd9aaa..fe9cfd792 100644 --- a/src/browser/base/content/zen-styles/zen-sidebar-panels.css +++ b/src/browser/base/content/zen-styles/zen-sidebar-panels.css @@ -129,7 +129,6 @@ position: absolute; top: 50%; left: 50%; - transform: translate(-50%, -50%); opacity: 0; transition: opacity 0.1s ease-in-out; pointer-events: none; @@ -140,10 +139,6 @@ } } -.zen-split-view-splitter[orient='vertical']::before { - transform: translate(-75%, -50%); -} - .zen-sidebar-web-panel-splitter[side='right'] { left: 100%; } diff --git a/src/browser/base/zen-components/ZenCompactMode.mjs b/src/browser/base/zen-components/ZenCompactMode.mjs index e95c31ab4..b378a7e31 100644 --- a/src/browser/base/zen-components/ZenCompactMode.mjs +++ b/src/browser/base/zen-components/ZenCompactMode.mjs @@ -141,10 +141,17 @@ var gZenCompactModeManager = { this.animateCompactMode(); }, - getAndApplySidebarWidth() { + // NOTE: Dont actually use event, it's just so we make sure + // the caller is from the ResizeObserver + getAndApplySidebarWidth(event = undefined) { let sidebarWidth = this.sidebar.getBoundingClientRect().width; if (sidebarWidth > 1) { gZenUIManager.restoreScrollbarState(); + // Second variable to get the genuine width of the sidebar + this.sidebar.style.setProperty('--actual-zen-sidebar-width', `${sidebarWidth}px`); + if (event && this.preference) { + return; + } this.sidebar.style.setProperty('--zen-sidebar-width', `${sidebarWidth}px`); } return sidebarWidth; @@ -161,8 +168,12 @@ var gZenCompactModeManager = { !this.sidebar.hasAttribute('zen-has-empty-tab') && !this.sidebar.hasAttribute('zen-has-hover'); // Do this so we can get the correct width ONCE compact mode styled have been applied + const titlebar = this.sidebar.querySelector('#titlebar'); if (canAnimate) { this.sidebar.setAttribute('animate', 'true'); + titlebar.setAttribute('has-animated-padding', 'true'); + } else { + titlebar.removeAttribute('has-animated-padding'); } this.sidebar.style.removeProperty('margin-right'); this.sidebar.style.removeProperty('margin-left'); From eda9b1f20b80fc9a247b4852b67053c4ea40a902 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Thu, 6 Mar 2025 22:40:00 +0100 Subject: [PATCH 049/127] The split view dragging should always show the cursor pointer --- src/browser/base/content/zen-styles/zen-decks.css | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-decks.css b/src/browser/base/content/zen-styles/zen-decks.css index c89cc0727..63507963e 100644 --- a/src/browser/base/content/zen-styles/zen-decks.css +++ b/src/browser/base/content/zen-styles/zen-decks.css @@ -256,9 +256,12 @@ height: 14px; } - &.zen-tab-rearrange-button image { - transform: rotate(90deg); + &.zen-tab-rearrange-button { cursor: move; + + & image { + transform: rotate(90deg); + } } } From 0d499b3c25d6b14ac833e50ab911747389f19b93 Mon Sep 17 00:00:00 2001 From: Samuel <36420837+Samueru-sama@users.noreply.github.com> Date: Thu, 6 Mar 2025 22:33:54 -0400 Subject: [PATCH 050/127] fix crash on sleep by switching appimage runtime This also has the benefit of faster launch times Signed-off-by: Samuel <36420837+Samueru-sama@users.noreply.github.com> --- .github/workflows/build.yml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d8e344caf..b22341ca6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -384,6 +384,8 @@ jobs: - name: Execute AppImage build run: | set -eux + export ARCH=${{ matrix.arch }} + UPINFO="gh-releases-zsync|$GITHUB_REPOSITORY_OWNER|desktop|latest|zen-$ARCH.AppImage.zsync" rm AppDir/.DirIcon || true cp configs/branding/${{ inputs.update_branch }}/logo128.png AppDir/usr/share/icons/hicolor/128x128/apps/zen.png cp configs/branding/${{ inputs.update_branch }}/logo128.png AppDir/zen.png && ln -s zen.png AppDir/.DirIcon @@ -396,18 +398,23 @@ jobs: APPDIR=AppDir tar -xvf *.tar.* && rm -rf *.tar.* mv zen/* $APPDIR/ - wget https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage + wget "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage" + wget "https://github.com/VHSgunzo/uruntime/releases/latest/download/uruntime-appimage-squashfs-lite-$ARCH" chmod +x *.AppImage + chmod +x ./uruntime-appimage-squashfs-lite-"$ARCH" chmod +x ./AppDir/AppRun + + # keep the uruntime mountpoint (massively speeds up launch time) + sed -i 's|URUNTIME_MOUNT=[0-9]|URUNTIME_MOUNT=0|' ./uruntime-appimage-squashfs-lite-"$ARCH" + echo "AppDir: $APPDIR" ls -al find . ls -al "$APPDIR" - ARCH=${{ matrix.arch }} ./appimagetool-x86_64.AppImage --comp zstd --mksquashfs-opt -Xcompression-level --mksquashfs-opt 10 \ - -u "gh-releases-zsync|$GITHUB_REPOSITORY_OWNER|desktop|latest|zen-${{ matrix.arch }}.AppImage.zsync" \ - "$APPDIR" zen-${{ matrix.arch }}.AppImage + ./appimagetool-x86_64.AppImage -u "$UPINFO" "$APPDIR" zen-"$ARCH".AppImage --runtime-file ./uruntime-appimage-squashfs-lite-"$ARCH" mkdir dist mv zen*AppImage* dist/. + unset ARCH - name: Upload artifact uses: actions/upload-artifact@v4 From 3325dc0d9f5aea1321abe678b8e203bcb9f97dd6 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Fri, 7 Mar 2025 11:54:57 +0100 Subject: [PATCH 051/127] Fixed session restore identifying the empty tab as a normal one --- .../base/content/zen-styles/zen-welcome.css | 5 +- .../base/zen-components/ZenWelcome.mjs | 4 +- .../base/zen-components/ZenWorkspaces.mjs | 3 +- .../sessionstore/SessionStore-sys-mjs.patch | 20 ++++++- .../tabbrowser/content/tabbrowser-js.patch | 58 +++++++++++-------- .../shared/zen-icons/lin/essential-add.svg | 2 +- 6 files changed, 60 insertions(+), 32 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-welcome.css b/src/browser/base/content/zen-styles/zen-welcome.css index 4d1d4c092..927c137d1 100644 --- a/src/browser/base/content/zen-styles/zen-welcome.css +++ b/src/browser/base/content/zen-styles/zen-welcome.css @@ -86,8 +86,9 @@ width: 100%; height: 100%; opacity: 0; - color: var(--zen-primary-color); - fill: var(--zen-primary-color); + color: currentColor; + fill: currentColor; + -moz-context-properties: fill, fill-opacity; background-image: url(chrome://browser/skin/zen-icons/essential-add.svg); background-size: 15%; background-repeat: no-repeat; diff --git a/src/browser/base/zen-components/ZenWelcome.mjs b/src/browser/base/zen-components/ZenWelcome.mjs index de91b7e01..9e19d08fd 100644 --- a/src/browser/base/zen-components/ZenWelcome.mjs +++ b/src/browser/base/zen-components/ZenWelcome.mjs @@ -454,9 +454,7 @@ async fadeOut() { gZenThemePicker.panel.removeAttribute('noautohide'); gZenThemePicker.panel.removeAttribute('consumeoutsideclicks'); - if (AppConstants.platform != 'macosx') { - await animate(gZenThemePicker.panel, { opacity: [1, 0] }); - } + await animate(gZenThemePicker.panel, { opacity: [1, 0] }); gZenThemePicker.panel.hidePopup(); gZenThemePicker.panel.removeAttribute('style'); }, diff --git a/src/browser/base/zen-components/ZenWorkspaces.mjs b/src/browser/base/zen-components/ZenWorkspaces.mjs index cc558e72e..53f911a36 100644 --- a/src/browser/base/zen-components/ZenWorkspaces.mjs +++ b/src/browser/base/zen-components/ZenWorkspaces.mjs @@ -626,7 +626,8 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { if ( (currentTab.isEmpty && (currentTab.getAttribute('image') === gPageIcons[currentTabURL] || !currentTab.hasAttribute('image'))) || - currentTab.hasAttribute('zen-empty-tab') + currentTab.hasAttribute('zen-empty-tab') || + currentTab._possibleEmptyTab ) { this.selectEmptyTab(); this._removedByStartupPage = true; diff --git a/src/browser/components/sessionstore/SessionStore-sys-mjs.patch b/src/browser/components/sessionstore/SessionStore-sys-mjs.patch index de0a9684b..9657c5a97 100644 --- a/src/browser/components/sessionstore/SessionStore-sys-mjs.patch +++ b/src/browser/components/sessionstore/SessionStore-sys-mjs.patch @@ -1,7 +1,16 @@ diff --git a/browser/components/sessionstore/SessionStore.sys.mjs b/browser/components/sessionstore/SessionStore.sys.mjs -index f814772114948f87cbb3c3a7231c95ea1f68d776..296cce151690b31a6e136dd5046a2697fb46fe45 100644 +index f814772114948f87cbb3c3a7231c95ea1f68d776..f7d1f1f05f33b42be6856fad52ee323751af56ee 100644 --- a/browser/components/sessionstore/SessionStore.sys.mjs +++ b/browser/components/sessionstore/SessionStore.sys.mjs +@@ -3171,7 +3171,7 @@ var SessionStoreInternal = { + if (!isPrivateWindow && tabState.isPrivate) { + return; + } +- if (aTab == aWindow.FirefoxViewHandler.tab) { ++ if (aTab == aWindow.FirefoxViewHandler.tab || aTab.hasAttribute("zen-empty-tab")) { + return; + } + @@ -3881,6 +3881,7 @@ var SessionStoreInternal = { aWindow.gBrowser.selectedTab = newTab; } @@ -27,6 +36,15 @@ index f814772114948f87cbb3c3a7231c95ea1f68d776..296cce151690b31a6e136dd5046a2697 continue; } let tabData = lazy.TabState.collect(tab, TAB_CUSTOM_VALUES.get(tab)); +@@ -5381,7 +5382,7 @@ var SessionStoreInternal = { + // We don't store the Firefox View tab in Session Store, so if it was the last selected "tab" when + // a window is closed, point to the first item in the tab strip instead (it will never be the Firefox View tab, + // since it's only inserted into the tab strip after it's selected). +- if (aWindow.FirefoxViewHandler.tab?.selected) { ++ if (aWindow.FirefoxViewHandler.tab?.selected || tabbrowser.selectedTab.hasAttribute("zen-empty-tab")) { + selectedIndex = 1; + winData.title = tabbrowser.tabs[0].label; + } @@ -6086,6 +6087,18 @@ var SessionStoreInternal = { // Most of tabData has been restored, now continue with restoring diff --git a/src/browser/components/tabbrowser/content/tabbrowser-js.patch b/src/browser/components/tabbrowser/content/tabbrowser-js.patch index 1ccc22b36..685b89576 100644 --- a/src/browser/components/tabbrowser/content/tabbrowser-js.patch +++ b/src/browser/components/tabbrowser/content/tabbrowser-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js -index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867792a2220 100644 +index 628aa6596627c85efe361fc1ece8fd58f7ee653e..10960c3fb00a00dcdcc2e2658ebff24f25d2514c 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js @@ -412,11 +412,50 @@ @@ -352,7 +352,17 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 tab.toggleAttribute("pinned", true); this.tabContainer._invalidateCachedTabs(); // Then ensure all the tab open/pinning information is sent. -@@ -3693,7 +3815,7 @@ +@@ -3503,6 +3625,9 @@ + let leftoverTab = this.selectedTab; + this.selectedTab = tabToSelect; + this.removeTab(leftoverTab); ++ } ++ else { ++ this.selectedTab._possibleEmptyTab = true; + } + + if (tabs.length > 1 || !tabs[0].selected) { +@@ -3693,7 +3818,7 @@ // Ensure we have an index if one was not provided. if (typeof index != "number") { // Move the new tab after another tab if needed, to the end otherwise. @@ -361,7 +371,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 if ( !bulkOrderedOpen && ((openerTab && -@@ -3736,18 +3858,18 @@ +@@ -3736,18 +3861,18 @@ // Ensure index is within bounds. if (tab.pinned) { @@ -384,7 +394,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 if (tabAfter && tabAfter.group == tabGroup) { // Place at the front of, or between tabs in, the same tab group this.tabContainer.insertBefore(tab, tabAfter); -@@ -4059,6 +4181,9 @@ +@@ -4059,6 +4184,9 @@ return; } @@ -394,7 +404,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 this.removeTabs(selectedTabs); } -@@ -4391,6 +4516,7 @@ +@@ -4391,6 +4519,7 @@ skipSessionStore, } = {} ) { @@ -402,7 +412,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 if (UserInteraction.running("browser.tabs.opening", window)) { UserInteraction.finish("browser.tabs.opening", window); } -@@ -4407,6 +4533,12 @@ +@@ -4407,6 +4536,12 @@ TelemetryStopwatch.start("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab); } @@ -415,7 +425,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 // Handle requests for synchronously removing an already // asynchronously closing tab. if (!animate && aTab.closing) { -@@ -4421,7 +4553,9 @@ +@@ -4421,7 +4556,9 @@ // frame created for it (for example, by updating the visually selected // state). let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width; @@ -426,7 +436,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 if ( !this._beginRemoveTab(aTab, { closeWindowFastpath: true, -@@ -4435,7 +4569,6 @@ +@@ -4435,7 +4572,6 @@ TelemetryStopwatch.cancel("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab); return; } @@ -434,7 +444,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 let lockTabSizing = !this.tabContainer.verticalMode && !aTab.pinned && -@@ -4574,14 +4707,14 @@ +@@ -4574,14 +4710,14 @@ !!this.tabsInCollapsedTabGroups.length; if ( aTab.visible && @@ -451,7 +461,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 if (closeWindow) { // We've already called beforeunload on all the relevant tabs if we get here, -@@ -4605,6 +4738,7 @@ +@@ -4605,6 +4741,7 @@ newTab = true; } @@ -459,7 +469,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 aTab._endRemoveArgs = [closeWindow, newTab]; // swapBrowsersAndCloseOther will take care of closing the window without animation. -@@ -4645,9 +4779,7 @@ +@@ -4645,9 +4782,7 @@ aTab._mouseleave(); if (newTab) { @@ -470,7 +480,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 } else { TabBarVisibility.update(); } -@@ -4776,6 +4908,8 @@ +@@ -4776,6 +4911,8 @@ this.tabs[i]._tPos = i; } @@ -479,7 +489,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 if (!this._windowIsClosing) { if (wasPinned) { this.tabContainer._positionPinnedTabs(); -@@ -4994,7 +5128,7 @@ +@@ -4994,7 +5131,7 @@ !excludeTabs.has(aTab.owner) && Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose") ) { @@ -488,7 +498,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 } // Try to find a remaining tab that comes after the given tab -@@ -5016,7 +5150,7 @@ +@@ -5016,7 +5153,7 @@ } if (tab) { @@ -497,7 +507,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 } // If no qualifying visible tab was found, see if there is a tab in -@@ -5434,10 +5568,10 @@ +@@ -5434,10 +5571,10 @@ SessionStore.deleteCustomTabValue(aTab, "hiddenBy"); } @@ -510,7 +520,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 aTab.selected || aTab.closing || // Tabs that are sharing the screen, microphone or camera cannot be hidden. -@@ -5675,7 +5809,7 @@ +@@ -5675,7 +5812,7 @@ // Don't allow mixing pinned and unpinned tabs. if (aTab.pinned) { @@ -519,7 +529,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 } else { aIndex = Math.max(aIndex, this.pinnedTabCount); } -@@ -5684,11 +5818,18 @@ +@@ -5684,11 +5821,18 @@ } this._handleTabMove(aTab, () => { @@ -541,7 +551,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 neighbor.after(aTab); } else { this.tabContainer.insertBefore(aTab, neighbor); -@@ -5697,7 +5838,7 @@ +@@ -5697,7 +5841,7 @@ } moveTabToGroup(aTab, aGroup) { @@ -550,7 +560,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 return; } if (aTab.group && aTab.group.id === aGroup.id) { -@@ -5721,6 +5862,10 @@ +@@ -5721,6 +5865,10 @@ moveActionCallback(); @@ -561,7 +571,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 // Clear tabs cache after moving nodes because the order of tabs may have // changed. this.tabContainer._invalidateCachedTabs(); -@@ -5771,7 +5916,7 @@ +@@ -5771,7 +5919,7 @@ createLazyBrowser, }; @@ -570,7 +580,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 if (aIndex < numPinned || (aTab.pinned && aIndex == numPinned)) { params.pinned = true; } -@@ -7415,6 +7560,7 @@ +@@ -7415,6 +7563,7 @@ aWebProgress.isTopLevel ) { this.mTab.setAttribute("busy", "true"); @@ -578,7 +588,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 gBrowser._tabAttrModified(this.mTab, ["busy"]); this.mTab._notselectedsinceload = !this.mTab.selected; } -@@ -8381,7 +8527,7 @@ var TabContextMenu = { +@@ -8381,7 +8530,7 @@ var TabContextMenu = { ); contextUnpinSelectedTabs.hidden = !this.contextTab.pinned || !multiselectionContext; @@ -587,7 +597,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 // Move Tab items let contextMoveTabOptions = document.getElementById( "context_moveTabOptions" -@@ -8414,7 +8560,7 @@ var TabContextMenu = { +@@ -8414,7 +8563,7 @@ var TabContextMenu = { let contextMoveTabToStart = document.getElementById("context_moveToStart"); let isFirstTab = tabsToMove[0] == visibleTabs[0] || @@ -596,7 +606,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..e80828e9e72faa3652cd218810b98867 contextMoveTabToStart.disabled = isFirstTab && allSelectedTabsAdjacent; document.getElementById("context_openTabInWindow").disabled = -@@ -8647,6 +8793,7 @@ var TabContextMenu = { +@@ -8647,6 +8796,7 @@ var TabContextMenu = { if (this.contextTab.multiselected) { gBrowser.removeMultiSelectedTabs(); } else { diff --git a/src/browser/themes/shared/zen-icons/lin/essential-add.svg b/src/browser/themes/shared/zen-icons/lin/essential-add.svg index d2345aa60..7b9858443 100644 --- a/src/browser/themes/shared/zen-icons/lin/essential-add.svg +++ b/src/browser/themes/shared/zen-icons/lin/essential-add.svg @@ -1 +1 @@ - + From 65433172f3dc527388f8574d7c2f664aedc5d235 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Fri, 7 Mar 2025 11:59:00 +0100 Subject: [PATCH 052/127] Added a corner radius to tab icons --- .../themes/shared/tabbrowser/tabs-css.patch | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/browser/themes/shared/tabbrowser/tabs-css.patch b/src/browser/themes/shared/tabbrowser/tabs-css.patch index 8d7b707e9..7a3de36e6 100644 --- a/src/browser/themes/shared/tabbrowser/tabs-css.patch +++ b/src/browser/themes/shared/tabbrowser/tabs-css.patch @@ -1,5 +1,5 @@ diff --git a/browser/themes/shared/tabbrowser/tabs.css b/browser/themes/shared/tabbrowser/tabs.css -index 01815c2114a627e5cac183c702bd82f1bd4f58f8..ad3686a4bcac0331d86f5e95ecdb6f023b2641bf 100644 +index 01815c2114a627e5cac183c702bd82f1bd4f58f8..7b20eb17b53cfe13b8de968b1aa59c94b6468c0d 100644 --- a/browser/themes/shared/tabbrowser/tabs.css +++ b/browser/themes/shared/tabbrowser/tabs.css @@ -31,7 +31,7 @@ @@ -37,7 +37,15 @@ index 01815c2114a627e5cac183c702bd82f1bd4f58f8..ad3686a4bcac0331d86f5e95ecdb6f02 &::before { position: absolute; -@@ -502,7 +501,7 @@ +@@ -437,6 +436,7 @@ + .tab-icon-image { + -moz-context-properties: fill, stroke; + fill: currentColor; ++ border-radius: 4px; + + /* Apply crisp rendering for favicons at exactly 2dppx resolution */ + @media (resolution: 2dppx) { +@@ -502,7 +502,7 @@ z-index: 1; /* Overlay tab title */ #tabbrowser-tabs[orient=vertical] & { @@ -46,7 +54,7 @@ index 01815c2114a627e5cac183c702bd82f1bd4f58f8..ad3686a4bcac0331d86f5e95ecdb6f02 } &[crashed] { -@@ -510,7 +509,7 @@ +@@ -510,7 +510,7 @@ } #tabbrowser-tabs[orient="vertical"]:not([expanded]) &:not([crashed]), @@ -55,7 +63,7 @@ index 01815c2114a627e5cac183c702bd82f1bd4f58f8..ad3686a4bcac0331d86f5e95ecdb6f02 &[soundplaying] { list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-playing-small.svg"); } -@@ -572,7 +571,7 @@ +@@ -572,7 +572,7 @@ } #tabbrowser-tabs[orient="vertical"]:not([expanded]) &:is([soundplaying], [muted], [activemedia-blocked]), @@ -64,7 +72,7 @@ index 01815c2114a627e5cac183c702bd82f1bd4f58f8..ad3686a4bcac0331d86f5e95ecdb6f02 &[crashed] { display: revert; } -@@ -586,7 +585,7 @@ +@@ -586,7 +586,7 @@ --button-min-height-small: 24px; --button-border-radius: var(--border-radius-small); @@ -73,7 +81,7 @@ index 01815c2114a627e5cac183c702bd82f1bd4f58f8..ad3686a4bcac0331d86f5e95ecdb6f02 &:is([soundplaying], [muted], [activemedia-blocked]) { display: block; } -@@ -617,14 +616,14 @@ +@@ -617,14 +617,14 @@ } &[textoverflow] { @@ -92,7 +100,7 @@ index 01815c2114a627e5cac183c702bd82f1bd4f58f8..ad3686a4bcac0331d86f5e95ecdb6f02 direction: rtl; mask-image: linear-gradient(to right, transparent, black var(--tab-label-mask-size)); } -@@ -1170,7 +1169,7 @@ +@@ -1170,7 +1170,7 @@ } } @@ -101,7 +109,7 @@ index 01815c2114a627e5cac183c702bd82f1bd4f58f8..ad3686a4bcac0331d86f5e95ecdb6f02 #vertical-tabs-newtab-button { appearance: none; min-height: var(--tab-min-height); -@@ -1181,7 +1180,7 @@ +@@ -1181,7 +1181,7 @@ margin-inline: var(--tab-inner-inline-margin); #tabbrowser-tabs[orient="vertical"]:not([expanded]) & > .toolbarbutton-text { @@ -110,7 +118,7 @@ index 01815c2114a627e5cac183c702bd82f1bd4f58f8..ad3686a4bcac0331d86f5e95ecdb6f02 } &:hover { -@@ -1205,7 +1204,7 @@ +@@ -1205,7 +1205,7 @@ * flex container. #tabs-newtab-button is a child of the arrowscrollbox where * we don't want a gap (between tabs), so we have to add some margin. */ @@ -119,7 +127,7 @@ index 01815c2114a627e5cac183c702bd82f1bd4f58f8..ad3686a4bcac0331d86f5e95ecdb6f02 margin-block: var(--tab-block-margin); } -@@ -1229,7 +1228,6 @@ +@@ -1229,7 +1229,6 @@ } #vertical-pinned-tabs-container { @@ -127,7 +135,7 @@ index 01815c2114a627e5cac183c702bd82f1bd4f58f8..ad3686a4bcac0331d86f5e95ecdb6f02 display: none; grid-template-columns: repeat(auto-fit, minmax(var(--tab-pinned-min-width-expanded), auto)); overflow-y: auto; -@@ -1439,7 +1437,7 @@ +@@ -1439,7 +1438,7 @@ toolbarbutton:not(#firefox-view-button), toolbarpaletteitem:not(#wrapper-firefox-view-button) ) ~ #tabbrowser-tabs { @@ -136,7 +144,7 @@ index 01815c2114a627e5cac183c702bd82f1bd4f58f8..ad3686a4bcac0331d86f5e95ecdb6f02 padding-inline-start: calc(var(--tab-overflow-pinned-tabs-width) + 2px); margin-inline-start: 2px; } -@@ -1473,7 +1471,6 @@ toolbar:not(#TabsToolbar) #firefox-view-button { +@@ -1473,7 +1472,6 @@ toolbar:not(#TabsToolbar) #firefox-view-button { list-style-image: url(chrome://global/skin/icons/plus.svg); } From f9f126a842fd2e6b53bfec8f4f1b809bd17b64c7 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Fri, 7 Mar 2025 12:12:32 +0100 Subject: [PATCH 053/127] Update tab selected text color to use !important for better visibility --- src/browser/themes/shared/tabbrowser/tabs-css.patch | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/browser/themes/shared/tabbrowser/tabs-css.patch b/src/browser/themes/shared/tabbrowser/tabs-css.patch index 7a3de36e6..3d8dd533e 100644 --- a/src/browser/themes/shared/tabbrowser/tabs-css.patch +++ b/src/browser/themes/shared/tabbrowser/tabs-css.patch @@ -1,5 +1,5 @@ diff --git a/browser/themes/shared/tabbrowser/tabs.css b/browser/themes/shared/tabbrowser/tabs.css -index 01815c2114a627e5cac183c702bd82f1bd4f58f8..7b20eb17b53cfe13b8de968b1aa59c94b6468c0d 100644 +index 01815c2114a627e5cac183c702bd82f1bd4f58f8..f47bd9c8490cd8fc4bb686ad0012ce70ab4bac8f 100644 --- a/browser/themes/shared/tabbrowser/tabs.css +++ b/browser/themes/shared/tabbrowser/tabs.css @@ -31,7 +31,7 @@ @@ -63,6 +63,15 @@ index 01815c2114a627e5cac183c702bd82f1bd4f58f8..7b20eb17b53cfe13b8de968b1aa59c94 &[soundplaying] { list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-playing-small.svg"); } +@@ -540,7 +540,7 @@ + background-image: linear-gradient(var(--audio-overlay-extra-background)), + linear-gradient(var(--toolbox-bgcolor)); + -moz-context-properties: fill; +- fill: var(--tab-selected-textcolor); ++ fill: var(--tab-selected-textcolor) !important; + color-scheme: var(--tab-selected-color-scheme); + border-radius: var(--border-radius-circle); + @@ -572,7 +572,7 @@ } From ea245cd213ce223a8da033ba6187b324a72b101d Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Fri, 7 Mar 2025 13:26:11 +0100 Subject: [PATCH 054/127] Common fixes before releasing --- .../zen-components/ZenPinnedTabManager.mjs | 2 +- .../base/zen-components/ZenSidebarManager.mjs | 4 +-- .../base/zen-components/ZenViewSplitter.mjs | 33 +++++++++++-------- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/browser/base/zen-components/ZenPinnedTabManager.mjs b/src/browser/base/zen-components/ZenPinnedTabManager.mjs index 66d84d6f3..31a1c927f 100644 --- a/src/browser/base/zen-components/ZenPinnedTabManager.mjs +++ b/src/browser/base/zen-components/ZenPinnedTabManager.mjs @@ -739,7 +739,7 @@ } // Check for essentials container else if (essentialTabsTarget) { - if (!draggedTab.hasAttribute('zen-essential')) { + if (!draggedTab.hasAttribute('zen-essential') && !draggedTab?.group?.hasAttribute('split-view-group')) { this.addToEssentials(draggedTab); moved = true; isVertical = false; diff --git a/src/browser/base/zen-components/ZenSidebarManager.mjs b/src/browser/base/zen-components/ZenSidebarManager.mjs index e734dddbf..00dca9459 100644 --- a/src/browser/base/zen-components/ZenSidebarManager.mjs +++ b/src/browser/base/zen-components/ZenSidebarManager.mjs @@ -182,8 +182,8 @@ class ZenBrowserManagerSidebar extends ZenDOMOperatedFeature { const leftMouseOffset = startLeft - mouseDownEvent.screenX; const moveListener = (mouseMoveEvent) => { window.requestAnimationFrame(() => { - let top = mouseMoveEvent.screenY + topMouseOffset; - let left = mouseMoveEvent.screenX + leftMouseOffset; + let top = mouseMoveEvent.clientY + topMouseOffset; + let left = mouseMoveEvent.clientX + leftMouseOffset; const wrapperBounds = this.sidebarWrapper.getBoundingClientRect(); top = Math.max(0, Math.min(top, wrapperBounds.height - sideBarHeight)); diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index 024a69e58..fac04a298 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -184,7 +184,8 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { this.fakeBrowser || !this._lastOpenedTab || (this._lastOpenedTab && - this._lastOpenedTab.getAttribute('zen-workspace-id') !== draggedTab.getAttribute('zen-workspace-id')) + (this._lastOpenedTab.getAttribute('zen-workspace-id') !== draggedTab.getAttribute('zen-workspace-id') || + this._lastOpenedTab.hasAttribute('zen-essential'))) ) { return; } @@ -1590,19 +1591,23 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { this._maybeRemoveFakeBrowser(false); if (browserContainer) { - gZenUIManager.motion.animate( - browserContainer, - { - scale: [0.97, 1], - opacity: [0, 1], - }, - { - type: 'spring', - bounce: 0.4, - duration: 0.2, - delay: 0.1, - } - ); + gZenUIManager.motion + .animate( + browserContainer, + { + scale: [0.97, 1], + opacity: [0, 1], + }, + { + type: 'spring', + bounce: 0.4, + duration: 0.2, + delay: 0.1, + } + ) + .then(() => { + gBrowser.tabbox.removeAttribute('style'); + }); } return true; } From ad491edee3fa2be57ce44f83bf4face2cd61b25c Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Fri, 7 Mar 2025 13:27:51 +0100 Subject: [PATCH 055/127] Make sure to show split views group as selected when multiselecting --- src/browser/base/content/zen-styles/zen-folders.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/base/content/zen-styles/zen-folders.css b/src/browser/base/content/zen-styles/zen-folders.css index 42ef4c01d..a9f162cab 100644 --- a/src/browser/base/content/zen-styles/zen-folders.css +++ b/src/browser/base/content/zen-styles/zen-folders.css @@ -60,7 +60,7 @@ tab-group[split-view-group] { } } - &:has(> tab[visuallyselected]) { + &:has(> tab:is([visuallyselected], [multiselected])) { background-color: var(--tab-selected-bgcolor); box-shadow: var(--tab-selected-shadow); From 9466f6ee86033d664583beac3a5db41807f4dc11 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Fri, 7 Mar 2025 13:33:18 +0100 Subject: [PATCH 056/127] Fixed dragging multiple tabs with split view groups --- .../tabbrowser/content/tabs-js.patch | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/browser/components/tabbrowser/content/tabs-js.patch b/src/browser/components/tabbrowser/content/tabs-js.patch index 44e4b7c45..8de6e1dd6 100644 --- a/src/browser/components/tabbrowser/content/tabs-js.patch +++ b/src/browser/components/tabbrowser/content/tabs-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js -index fa96568d366fd3608f9bd583fa793150bd815c8b..1e007c37cd204c63afad24c8b6d9201e6a02da2d 100644 +index fa96568d366fd3608f9bd583fa793150bd815c8b..693549cec63365c5f338410429f922fa5b7f3f81 100644 --- a/browser/components/tabbrowser/content/tabs.js +++ b/browser/components/tabbrowser/content/tabs.js @@ -94,7 +94,7 @@ @@ -385,7 +385,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..1e007c37cd204c63afad24c8b6d9201e ); if (this.#rtlMode) { -@@ -2347,8 +2383,12 @@ +@@ -2347,8 +2383,16 @@ (lastMovingTabScreen + tabSize); translate = Math.min(Math.max(translate, firstBound), lastBound); @@ -395,12 +395,16 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..1e007c37cd204c63afad24c8b6d9201e + draggedTab.group.style.transform = `${translateAxis}(${translate}px)`; + } else { + for (let tab of movingTabs) { -+ tab.style.transform = `${translateAxis}(${translate}px)`; ++ if (tab.group?.hasAttribute("split-view-group")) { ++ tab.group.style.transform = `${translateAxis}(${translate}px)`; ++ } else { ++ tab.style.transform = `${translateAxis}(${translate}px)`; ++ } + } } dragData.translatePos = translate; -@@ -2484,12 +2524,16 @@ +@@ -2484,12 +2528,16 @@ // Shift background tabs to leave a gap where the dragged tab // would currently be dropped. for (let tab of tabs) { @@ -418,7 +422,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..1e007c37cd204c63afad24c8b6d9201e if (tab.group?.tabs[0] == tab) { tab.group.style.setProperty( "--tabgroup-dragover-transform", -@@ -2541,8 +2585,9 @@ +@@ -2541,8 +2589,9 @@ ); } @@ -430,7 +434,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..1e007c37cd204c63afad24c8b6d9201e return; } -@@ -2553,6 +2598,7 @@ +@@ -2553,6 +2602,7 @@ tab.style.transform = ""; if (tab.group) { tab.group.style.removeProperty("--tabgroup-dragover-transform"); @@ -438,7 +442,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..1e007c37cd204c63afad24c8b6d9201e } tab.removeAttribute("dragover-createGroup"); } -@@ -2604,7 +2650,7 @@ +@@ -2604,7 +2654,7 @@ movingTab._moveTogetherSelectedTabsData.newIndex = movingTabNewIndex; movingTab._moveTogetherSelectedTabsData.animate = false; }; @@ -447,7 +451,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..1e007c37cd204c63afad24c8b6d9201e postTransitionCleanup(); } else { let onTransitionEnd = transitionendEvent => { -@@ -2707,9 +2753,9 @@ +@@ -2707,9 +2757,9 @@ function newIndex(aTab, index) { // Don't allow mixing pinned and unpinned tabs. if (aTab.pinned) { @@ -459,7 +463,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..1e007c37cd204c63afad24c8b6d9201e } } -@@ -2793,7 +2839,7 @@ +@@ -2793,7 +2843,7 @@ } _notifyBackgroundTab(aTab) { From 0575373167845ebe86dba7b91c22f16fb972b987 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Fri, 7 Mar 2025 13:37:28 +0100 Subject: [PATCH 057/127] Fixed dragging split views tabs outisde of the container --- .../tabbrowser/content/tabs-js.patch | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/browser/components/tabbrowser/content/tabs-js.patch b/src/browser/components/tabbrowser/content/tabs-js.patch index 8de6e1dd6..09123e634 100644 --- a/src/browser/components/tabbrowser/content/tabs-js.patch +++ b/src/browser/components/tabbrowser/content/tabs-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js -index fa96568d366fd3608f9bd583fa793150bd815c8b..693549cec63365c5f338410429f922fa5b7f3f81 100644 +index fa96568d366fd3608f9bd583fa793150bd815c8b..9151fa411faa9689c7b079fafe0fab1234177f40 100644 --- a/browser/components/tabbrowser/content/tabs.js +++ b/browser/components/tabbrowser/content/tabs.js @@ -94,7 +94,7 @@ @@ -385,26 +385,20 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..693549cec63365c5f338410429f922fa ); if (this.#rtlMode) { -@@ -2347,8 +2383,16 @@ - (lastMovingTabScreen + tabSize); +@@ -2348,7 +2384,11 @@ translate = Math.min(Math.max(translate, firstBound), lastBound); -- for (let tab of movingTabs) { + for (let tab of movingTabs) { - tab.style.transform = `${translateAxis}(${translate}px)`; -+ if (draggedTab.group?.hasAttribute("split-view-group")) { -+ draggedTab.group.style.transform = `${translateAxis}(${translate}px)`; -+ } else { -+ for (let tab of movingTabs) { -+ if (tab.group?.hasAttribute("split-view-group")) { -+ tab.group.style.transform = `${translateAxis}(${translate}px)`; -+ } else { -+ tab.style.transform = `${translateAxis}(${translate}px)`; -+ } ++ if (tab.group?.hasAttribute("split-view-group")) { ++ tab.group.style.transform = `${translateAxis}(${translate}px)`; ++ } else { ++ tab.style.transform = `${translateAxis}(${translate}px)`; + } } dragData.translatePos = translate; -@@ -2484,12 +2528,16 @@ +@@ -2484,12 +2524,16 @@ // Shift background tabs to leave a gap where the dragged tab // would currently be dropped. for (let tab of tabs) { @@ -422,7 +416,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..693549cec63365c5f338410429f922fa if (tab.group?.tabs[0] == tab) { tab.group.style.setProperty( "--tabgroup-dragover-transform", -@@ -2541,8 +2589,9 @@ +@@ -2541,8 +2585,9 @@ ); } @@ -434,7 +428,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..693549cec63365c5f338410429f922fa return; } -@@ -2553,6 +2602,7 @@ +@@ -2553,6 +2598,7 @@ tab.style.transform = ""; if (tab.group) { tab.group.style.removeProperty("--tabgroup-dragover-transform"); @@ -442,7 +436,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..693549cec63365c5f338410429f922fa } tab.removeAttribute("dragover-createGroup"); } -@@ -2604,7 +2654,7 @@ +@@ -2604,7 +2650,7 @@ movingTab._moveTogetherSelectedTabsData.newIndex = movingTabNewIndex; movingTab._moveTogetherSelectedTabsData.animate = false; }; @@ -451,7 +445,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..693549cec63365c5f338410429f922fa postTransitionCleanup(); } else { let onTransitionEnd = transitionendEvent => { -@@ -2707,9 +2757,9 @@ +@@ -2707,9 +2753,9 @@ function newIndex(aTab, index) { // Don't allow mixing pinned and unpinned tabs. if (aTab.pinned) { @@ -463,7 +457,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..693549cec63365c5f338410429f922fa } } -@@ -2793,7 +2843,7 @@ +@@ -2793,7 +2839,7 @@ } _notifyBackgroundTab(aTab) { From 39fdda89585131dd691be7de02eb34770351533d Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Fri, 7 Mar 2025 13:59:23 +0100 Subject: [PATCH 058/127] Added support to unsplit tabs when dragging them to the sidebar --- .../base/zen-components/ZenViewSplitter.mjs | 33 +++++++++++++++++-- .../tabbrowser/content/tabs-js.patch | 11 ++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index fac04a298..97d76ffb7 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -1588,7 +1588,9 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { this.splitTabs([draggedTab, droppedOnTab], gridType, 1); } } - this._maybeRemoveFakeBrowser(false); + window.requestAnimationFrame(() => { + this._maybeRemoveFakeBrowser(false); + }); if (browserContainer) { gZenUIManager.motion @@ -1606,12 +1608,39 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { } ) .then(() => { - gBrowser.tabbox.removeAttribute('style'); + this._maybeRemoveFakeBrowser(false); }); } return true; } + handleTabDrop(event, urls, replace, inBackground) { + if (!inBackground || replace || urls.length !== 1) { + return false; + } + const url = urls[0]; + if (!url.startsWith('panel-')) { + return false; + } + const browserContainer = document.getElementById(url); + const browser = browserContainer?.querySelector('browser'); + if (!browser) { + return false; + } + const tab = gBrowser.getTabForBrowser(browser); + if (!tab) { + return false; + } + if (tab.splitView) { + // Unsplit the tab and exit from the drag view + this.dropZone?.removeAttribute('enabled'); + this.disableTabRearrangeView(event); + this.removeTabFromSplit(browserContainer); + return true; + } + return false; + } + /** * Gets or creates a tab group for split view tabs * @param {Array} tabs Initial tabs to add to the group if creating new diff --git a/src/browser/components/tabbrowser/content/tabs-js.patch b/src/browser/components/tabbrowser/content/tabs-js.patch index 09123e634..4c3e69d98 100644 --- a/src/browser/components/tabbrowser/content/tabs-js.patch +++ b/src/browser/components/tabbrowser/content/tabs-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js -index fa96568d366fd3608f9bd583fa793150bd815c8b..9151fa411faa9689c7b079fafe0fab1234177f40 100644 +index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a840ea19b 100644 --- a/browser/components/tabbrowser/content/tabs.js +++ b/browser/components/tabbrowser/content/tabs.js @@ -94,7 +94,7 @@ @@ -97,6 +97,15 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..9151fa411faa9689c7b079fafe0fab12 postTransitionCleanup(); } else { let onTransitionEnd = transitionendEvent => { +@@ -1249,7 +1263,7 @@ + return; + } + } +- ++ if (gZenViewSplitter.handleTabDrop(event, urls, replace, inBackground)) return; + gBrowser.loadTabs(urls, { + inBackground, + replace, @@ -1279,13 +1293,23 @@ return; } From 3b86f317d17084de5f4b130c778d37769fdb2944 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Fri, 7 Mar 2025 14:07:49 +0100 Subject: [PATCH 059/127] Fixed animating split views in --- .github/workflows/linux-release-build.yml | 4 ++++ src/browser/base/zen-components/ZenViewSplitter.mjs | 9 ++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/linux-release-build.yml b/.github/workflows/linux-release-build.yml index b19c1f3c2..5246a9aa0 100644 --- a/.github/workflows/linux-release-build.yml +++ b/.github/workflows/linux-release-build.yml @@ -39,6 +39,10 @@ jobs: with: tool-cache: false + # Bug: https://github.com/actions/checkout/issues/1153 + - name: Remove zombie lock file + run: rm -f /home/ubuntu/actions-runner/_work/desktop/desktop/.git/modules/l10n/index.lock + - name: Checkout repository uses: actions/checkout@v4 with: diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index 97d76ffb7..b805cde16 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -223,7 +223,8 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { this.fakeBrowser.id = 'zen-split-view-fake-browser'; gBrowser.tabbox.appendChild(this.fakeBrowser); this.fakeBrowser.style.setProperty('--zen-split-view-fake-icon', `url(${draggedTab.getAttribute('image')})`); - Promise.all([ + draggedTab._visuallySelected = true; + this._finishAllAnimatingPromise = Promise.all([ gZenUIManager.motion.animate( gBrowser.tabbox, { @@ -245,7 +246,9 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { easing: 'ease-out', } ), - ]).then(() => { + ]); + this._finishAllAnimatingPromise.then(() => { + this._canDrop = true; draggedTab._visuallySelected = true; }); }, 100); @@ -1588,7 +1591,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { this.splitTabs([draggedTab, droppedOnTab], gridType, 1); } } - window.requestAnimationFrame(() => { + this._finishAllAnimatingPromise.then(() => { this._maybeRemoveFakeBrowser(false); }); From 124d5e0cdb1746a98438751c5a996026855108c0 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Fri, 7 Mar 2025 15:29:26 +0100 Subject: [PATCH 060/127] Enhance button hover effects with scaling transitions for improved interactivity --- .../base/content/zen-styles/zen-glance.css | 7 ++++++- .../zen-styles/zen-gradient-generator.css | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/browser/base/content/zen-styles/zen-glance.css b/src/browser/base/content/zen-styles/zen-glance.css index 4ea37f5db..3afbc6343 100644 --- a/src/browser/base/content/zen-styles/zen-glance.css +++ b/src/browser/base/content/zen-styles/zen-glance.css @@ -29,7 +29,7 @@ width: 32px; height: 32px; background: light-dark(rgb(24, 24, 24), rgb(231, 231, 231)); - transition: background 0.2s ease; + transition: background 0.05s ease, scale 0.05s ease; border-radius: 999px; appearance: none; box-shadow: 0 0 12px 1px rgba(0, 0, 0, 0.07); @@ -37,6 +37,11 @@ &:hover { background: light-dark(rgb(41, 41, 41), rgb(204, 204, 204)); + scale: 1.05; + } + + &:hover:active { + scale: 0.95; } & label { diff --git a/src/browser/base/content/zen-styles/zen-gradient-generator.css b/src/browser/base/content/zen-styles/zen-gradient-generator.css index a7ebca11d..09971dd3d 100644 --- a/src/browser/base/content/zen-styles/zen-gradient-generator.css +++ b/src/browser/base/content/zen-styles/zen-gradient-generator.css @@ -89,6 +89,7 @@ border-radius: 50%; cursor: pointer; position: relative; + transition: transform 0.1s; &::after { content: ''; position: absolute; @@ -99,6 +100,23 @@ outline: 2px solid var(--zen-toolbar-element-bg); border-radius: 50%; pointer-events: none; + transition: transform 0.1s; + } + + &:hover { + transform: scale(1.05); + + &::after { + transform: scale(1.05); + } + } + + &:hover:active { + transform: scale(0.95); + + &::after { + transform: scale(0.95); + } } } } From d8265d451320223e8c14bfa9581b764d91d1cc6e Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Fri, 7 Mar 2025 15:29:59 +0100 Subject: [PATCH 061/127] Remove zombie lock file in Windows release build workflow --- .github/workflows/windows-release-build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/windows-release-build.yml b/.github/workflows/windows-release-build.yml index ffa7ae764..59fd3a8c1 100644 --- a/.github/workflows/windows-release-build.yml +++ b/.github/workflows/windows-release-build.yml @@ -45,6 +45,10 @@ jobs: with: tool-cache: false + # Bug: https://github.com/actions/checkout/issues/1153 + - name: Remove zombie lock file + run: rm -f /home/ubuntu/actions-runner/_work/desktop/desktop/.git/modules/l10n/index.lock + - name: Checkout repository uses: actions/checkout@v4 with: From b69e8aebabfb5cd1c97de046ce3a173c28e15bea Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Fri, 7 Mar 2025 15:30:13 +0100 Subject: [PATCH 062/127] Refactor transition properties for improved readability in zen-glance.css --- src/browser/base/content/zen-styles/zen-glance.css | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/browser/base/content/zen-styles/zen-glance.css b/src/browser/base/content/zen-styles/zen-glance.css index 3afbc6343..0662e4e68 100644 --- a/src/browser/base/content/zen-styles/zen-glance.css +++ b/src/browser/base/content/zen-styles/zen-glance.css @@ -29,7 +29,9 @@ width: 32px; height: 32px; background: light-dark(rgb(24, 24, 24), rgb(231, 231, 231)); - transition: background 0.05s ease, scale 0.05s ease; + transition: + background 0.05s ease, + scale 0.05s ease; border-radius: 999px; appearance: none; box-shadow: 0 0 12px 1px rgba(0, 0, 0, 0.07); From 8e789732f9e911547f93c7f327247620362665fb Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Fri, 7 Mar 2025 16:25:36 +0100 Subject: [PATCH 063/127] Refactor CSS for vertical tabs and URL bar to improve layout and responsiveness --- .../zen-styles/zen-tabs/vertical-tabs.css | 10 ++++++++-- .../base/content/zen-styles/zen-urlbar.css | 18 +++++++++--------- .../base/content/zen-styles/zen-workspaces.css | 2 ++ .../themes/shared/urlbar-searchbar-css.patch | 13 ++++++++++++- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css index ccd32fe57..0f9982a22 100644 --- a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css +++ b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css @@ -373,6 +373,8 @@ overflow-y: auto; height: 100%; scrollbar-width: thin; + margin-left: calc(-1 * var(--zen-toolbox-padding)); + width: calc(100% + var(--zen-toolbox-padding) * 2); } #zen-browser-tabs-container { @@ -439,7 +441,7 @@ padding-right: 0; :root[zen-single-toolbar='true'] & { - & #urlbar:not([breakout-extend='true']) .urlbar-input-container { + & #urlbar:not([breakout-extend='true']):not([pageproxystate='invalid']) .urlbar-input-container { padding-left: 8px; padding-right: 4px; } @@ -1260,5 +1262,9 @@ .zen-workspace-tabs-section { position: absolute; transform: translateX(-100%); - min-width: 100%; + min-width: calc(100% - var(--zen-toolbox-padding) * 2); + + &:not(.zen-current-workspace-indicator) { + margin: 0 var(--zen-toolbox-padding); + } } diff --git a/src/browser/base/content/zen-styles/zen-urlbar.css b/src/browser/base/content/zen-styles/zen-urlbar.css index 75b27837e..337525531 100644 --- a/src/browser/base/content/zen-styles/zen-urlbar.css +++ b/src/browser/base/content/zen-styles/zen-urlbar.css @@ -80,7 +80,7 @@ position: relative; } -#urlbar:not([breakout-extend='true']) #identity-box:is(:not(.chromeUI), [pageproxystate='invalid']) { +#urlbar:not([breakout-extend='true']) #identity-box { margin-inline-end: 0 !important; } @@ -127,11 +127,11 @@ box-shadow: 0px 0px 90px -10px rgba(0, 0, 0, 0.6) !important; border: 1px solid hsla(0, 0%, 100%, 0.1) !important; backdrop-filter: none !important; - border-radius: 1rem !important; + border-radius: 0.8rem !important; } #urlbar-go-button { - margin: auto 0; + display: none; } :root[zen-single-toolbar='true'] { @@ -142,11 +142,11 @@ display: none; } - #identity-icon-box:not([open]) { - margin-inline-start: calc(-8px - 2 * var(--urlbar-icon-padding)) !important; + #identity-box:not([pageproxystate='invalid']) #identity-icon-box:not([open]) { + margin-inline-start: calc(-8px - 2 * var(--urlbar-icon-padding)); transform: translateX(100%); - opacity: 0; transition: all 0.1s ease; + opacity: 0; } #identity-permission-box > *:not(#permissions-granted-icon) { @@ -162,9 +162,9 @@ #identity-permission-box ), #urlbar:hover #identity-icon-box { - opacity: 1; + opacity: 1 !important; margin-inline-start: 0 !important; - transform: none; + transform: none !important; display: flex; #urlbar:not(:hover) & { transition: 0; @@ -176,7 +176,7 @@ } #urlbar:not([open]) { - #identity-box { + #identity-box:not([pageproxystate='invalid']) { order: 9; } } diff --git a/src/browser/base/content/zen-styles/zen-workspaces.css b/src/browser/base/content/zen-styles/zen-workspaces.css index ded029357..8e46cae98 100644 --- a/src/browser/base/content/zen-styles/zen-workspaces.css +++ b/src/browser/base/content/zen-styles/zen-workspaces.css @@ -452,6 +452,7 @@ /* Mark workspaces indicator */ #zen-current-workspace-indicator-container { + position: relative; margin-bottom: var(--zen-workspace-indicator-height); } @@ -465,6 +466,7 @@ align-items: center; flex-direction: row !important; max-width: 100%; + width: 100%; &::before { border-radius: var(--border-radius-medium); diff --git a/src/browser/themes/shared/urlbar-searchbar-css.patch b/src/browser/themes/shared/urlbar-searchbar-css.patch index 259fe7eaf..b41a61211 100644 --- a/src/browser/themes/shared/urlbar-searchbar-css.patch +++ b/src/browser/themes/shared/urlbar-searchbar-css.patch @@ -1,5 +1,5 @@ diff --git a/browser/themes/shared/urlbar-searchbar.css b/browser/themes/shared/urlbar-searchbar.css -index 574f83af7fa49ddcdff6711ca8b1d3bed1a35e0c..c2e8cb8b37438176db07a47e1e975ae1aea42252 100644 +index 574f83af7fa49ddcdff6711ca8b1d3bed1a35e0c..7919f21f6b0b4df2f197b9c6f0e134ff85d50d0a 100644 --- a/browser/themes/shared/urlbar-searchbar.css +++ b/browser/themes/shared/urlbar-searchbar.css @@ -5,7 +5,7 @@ @@ -22,3 +22,14 @@ index 574f83af7fa49ddcdff6711ca8b1d3bed1a35e0c..c2e8cb8b37438176db07a47e1e975ae1 width: calc(var(--urlbar-width) + 2 * var(--urlbar-margin-inline)); > .urlbar-input-container { +@@ -583,8 +585,8 @@ + .urlbar-revert-button, + .urlbar-go-button, + .search-go-button { +- width: calc(var(--urlbar-min-height) - 2px /* border */ - 2 * var(--urlbar-container-padding)); +- height: calc(var(--urlbar-min-height) - 2px /* border */ - 2 * var(--urlbar-container-padding)); ++ width: calc(var(--urlbar-min-height) + 2px /* border */ - 2 * var(--urlbar-container-padding)); ++ height: calc(var(--urlbar-min-height) + 2px /* border */ - 2 * var(--urlbar-container-padding)); + border-radius: var(--urlbar-icon-border-radius); + padding: var(--urlbar-icon-padding); + color: inherit; From 00654c168fc1fd5f27d3b90bda0f9b3719c75a2a Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Fri, 7 Mar 2025 16:26:30 +0100 Subject: [PATCH 064/127] Fix promise handling in ZenViewSplitter to prevent memory leaks --- src/browser/base/zen-components/ZenViewSplitter.mjs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index b805cde16..31cebad9b 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -247,10 +247,13 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { } ), ]); - this._finishAllAnimatingPromise.then(() => { - this._canDrop = true; - draggedTab._visuallySelected = true; - }); + if (this._finishAllAnimatingPromise) { + this._finishAllAnimatingPromise.then(() => { + this._canDrop = true; + draggedTab._visuallySelected = true; + this._finishAllAnimatingPromise = null; + }); + } }, 100); } From 4c7955b099f2b62298a7fcfdb2927da323112ab7 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Fri, 7 Mar 2025 17:04:27 +0100 Subject: [PATCH 065/127] Add actions cache variable exposure to build workflows --- .github/workflows/build.yml | 4 ---- .github/workflows/linux-release-build.yml | 7 +++++++ .github/workflows/macos-release-build.yml | 7 +++++++ .github/workflows/windows-release-build.yml | 7 +++++++ 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b22341ca6..bec46b34c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -471,10 +471,6 @@ jobs: submodules: recursive token: ${{ secrets.DEPLOY_KEY }} - - name: Git pull - run: | - git pull - - name: Download artifact uses: actions/download-artifact@v4 diff --git a/.github/workflows/linux-release-build.yml b/.github/workflows/linux-release-build.yml index 5246a9aa0..6de6c58d6 100644 --- a/.github/workflows/linux-release-build.yml +++ b/.github/workflows/linux-release-build.yml @@ -59,6 +59,13 @@ jobs: with: disable_annotations: true + - name: Expose actions cache variables + uses: actions/github-script@v6 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env['ACTIONS_CACHE_URL']) + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env['ACTIONS_RUNTIME_TOKEN']) + - name: Setup Git run: | git config --global user.email "mauro-balades@users.noreply.github.com" diff --git a/.github/workflows/macos-release-build.yml b/.github/workflows/macos-release-build.yml index 86340021d..13c9b0d13 100644 --- a/.github/workflows/macos-release-build.yml +++ b/.github/workflows/macos-release-build.yml @@ -47,6 +47,13 @@ jobs: with: disable_annotations: true + - name: Expose actions cache variables + uses: actions/github-script@v6 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env['ACTIONS_CACHE_URL']) + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env['ACTIONS_RUNTIME_TOKEN']) + - name: Setup Python uses: actions/setup-python@v5 # note: This will use the version defined in '.python-version' by default diff --git a/.github/workflows/windows-release-build.yml b/.github/workflows/windows-release-build.yml index 59fd3a8c1..602e397a4 100644 --- a/.github/workflows/windows-release-build.yml +++ b/.github/workflows/windows-release-build.yml @@ -65,6 +65,13 @@ jobs: with: disable_annotations: true + - name: Expose actions cache variables + uses: actions/github-script@v6 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env['ACTIONS_CACHE_URL']) + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env['ACTIONS_RUNTIME_TOKEN']) + - name: Setup Git run: | git config --global user.email "mauro-balades@users.noreply.github.com" From 5484aea042e959243ba45211188143ac6c05f720 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Fri, 7 Mar 2025 17:39:05 +0100 Subject: [PATCH 066/127] Enhance tab movement functionality with error handling and style reset for dragged tabs --- .../base/content/zen-styles/zen-decks.css | 3 + .../zen-components/ZenPinnedTabManager.mjs | 127 +++++++++--------- .../base/zen-components/ZenViewSplitter.mjs | 17 ++- 3 files changed, 81 insertions(+), 66 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-decks.css b/src/browser/base/content/zen-styles/zen-decks.css index 63507963e..96e6237dc 100644 --- a/src/browser/base/content/zen-styles/zen-decks.css +++ b/src/browser/base/content/zen-styles/zen-decks.css @@ -227,6 +227,9 @@ box-shadow: 0 0 0 1px var(--button-primary-border-color); gap: 0.8rem; transform: translateX(-50%); + box-shadow: 0 0 5px 1px rgba(0, 0, 0, 0.1); + border-top-left-radius: 0; + border-top-right-radius: 0; } :root:not([inDOMFullscreen='true']) .browserSidebarContainer:hover .zen-view-splitter-header-container, diff --git a/src/browser/base/zen-components/ZenPinnedTabManager.mjs b/src/browser/base/zen-components/ZenPinnedTabManager.mjs index 31a1c927f..eeb9301e0 100644 --- a/src/browser/base/zen-components/ZenPinnedTabManager.mjs +++ b/src/browser/base/zen-components/ZenPinnedTabManager.mjs @@ -718,72 +718,77 @@ } moveToAnotherTabContainerIfNecessary(event, movingTabs) { - const pinnedTabsTarget = - event.target.closest('#vertical-pinned-tabs-container') || event.target.closest('.zen-current-workspace-indicator'); - const essentialTabsTarget = event.target.closest('#zen-essentials-container'); - const tabsTarget = event.target.closest('#tabbrowser-arrowscrollbox'); + try { + const pinnedTabsTarget = + event.target.closest('#vertical-pinned-tabs-container') || event.target.closest('.zen-current-workspace-indicator'); + const essentialTabsTarget = event.target.closest('#zen-essentials-container'); + const tabsTarget = event.target.closest('#tabbrowser-arrowscrollbox'); - let isVertical = this.expandedSidebarMode; - let moved = false; - for (const draggedTab of movingTabs) { - let isRegularTabs = false; - // Check for pinned tabs container - if (pinnedTabsTarget) { - if (!draggedTab.pinned) { - gBrowser.pinTab(draggedTab); - moved = true; - } else if (draggedTab.hasAttribute('zen-essential')) { - this.removeEssentials(draggedTab, false); - moved = true; - } - } - // Check for essentials container - else if (essentialTabsTarget) { - if (!draggedTab.hasAttribute('zen-essential') && !draggedTab?.group?.hasAttribute('split-view-group')) { - this.addToEssentials(draggedTab); - moved = true; - isVertical = false; - } - } - // Check for normal tabs container - else if (tabsTarget || event.target.id === 'zen-tabs-wrapper') { - if (draggedTab.pinned && !draggedTab.hasAttribute('zen-essential')) { - gBrowser.unpinTab(draggedTab); - moved = true; - isRegularTabs = true; - } else if (draggedTab.hasAttribute('zen-essential')) { - this.removeEssentials(draggedTab); - moved = true; - isRegularTabs = true; - } - } - - // If the tab was moved, adjust its position relative to the target tab - if (moved) { - const targetTab = event.target.closest('.tabbrowser-tab'); - if (targetTab) { - const rect = targetTab.getBoundingClientRect(); - let newIndex = targetTab._tPos; - - if (isVertical) { - const middleY = targetTab.screenY + rect.height / 2; - if (!isRegularTabs && event.screenY > middleY) { - newIndex++; - } else if (isRegularTabs && event.screenY < middleY) { - newIndex--; - } - } else { - const middleX = targetTab.screenX + rect.width / 2; - if (event.screenX > middleX) { - newIndex++; - } + let isVertical = this.expandedSidebarMode; + let moved = false; + for (const draggedTab of movingTabs) { + let isRegularTabs = false; + // Check for pinned tabs container + if (pinnedTabsTarget) { + if (!draggedTab.pinned) { + gBrowser.pinTab(draggedTab); + moved = true; + } else if (draggedTab.hasAttribute('zen-essential')) { + this.removeEssentials(draggedTab, false); + moved = true; + } + } + // Check for essentials container + else if (essentialTabsTarget) { + if (!draggedTab.hasAttribute('zen-essential') && !draggedTab?.group?.hasAttribute('split-view-group')) { + this.addToEssentials(draggedTab); + moved = true; + isVertical = false; + } + } + // Check for normal tabs container + else if (tabsTarget || event.target.id === 'zen-tabs-wrapper') { + if (draggedTab.pinned && !draggedTab.hasAttribute('zen-essential')) { + gBrowser.unpinTab(draggedTab); + moved = true; + isRegularTabs = true; + } else if (draggedTab.hasAttribute('zen-essential')) { + this.removeEssentials(draggedTab); + moved = true; + isRegularTabs = true; + } + } + + // If the tab was moved, adjust its position relative to the target tab + if (moved) { + const targetTab = event.target.closest('.tabbrowser-tab'); + if (targetTab) { + const rect = targetTab.getBoundingClientRect(); + let newIndex = targetTab._tPos; + + if (isVertical) { + const middleY = targetTab.screenY + rect.height / 2; + if (!isRegularTabs && event.screenY > middleY) { + newIndex++; + } else if (isRegularTabs && event.screenY < middleY) { + newIndex--; + } + } else { + const middleX = targetTab.screenX + rect.width / 2; + if (event.screenX > middleX) { + newIndex++; + } + } + gBrowser.moveTabTo(draggedTab, newIndex); } - gBrowser.moveTabTo(draggedTab, newIndex); } } - } - return moved; + return moved; + } catch (ex) { + console.error('Error moving tabs:', ex); + return false; + } } async onLocationChange(browser) { diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index 31cebad9b..ac43a7c56 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -214,6 +214,9 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { this._draggingTab = draggedTab; gBrowser.selectedTab = oldTab; this._hasAnimated = true; + for (const tab of gBrowser.tabs) { + tab.style.removeProperty('transform'); + } const panelsWidth = gBrowser.tabbox.getBoundingClientRect().width; const halfWidth = panelsWidth / 2; this.fakeBrowser = document.createXULElement('vbox'); @@ -251,7 +254,6 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { this._finishAllAnimatingPromise.then(() => { this._canDrop = true; draggedTab._visuallySelected = true; - this._finishAllAnimatingPromise = null; }); } }, 100); @@ -267,7 +269,9 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { (event.target.closest('#tabbrowser-tabbox') && event.target != this.fakeBrowser) || (fakeBrowserRect && event.clientX > fakeBrowserRect.left && - event.clientX < fakeBrowserRect.left + fakeBrowserRect.width) || + event.clientX < fakeBrowserRect.left + fakeBrowserRect.width && + event.clientY > fakeBrowserRect.top && + event.clientY < fakeBrowserRect.top + fakeBrowserRect.height) || (event.screenX === 0 && event.screenY === 0) // It's equivalent to 0 if the event has been dropped ) { return; @@ -1594,9 +1598,11 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { this.splitTabs([draggedTab, droppedOnTab], gridType, 1); } } - this._finishAllAnimatingPromise.then(() => { - this._maybeRemoveFakeBrowser(false); - }); + if (this._finishAllAnimatingPromise) { + this._finishAllAnimatingPromise.then(() => { + this._maybeRemoveFakeBrowser(false); + }); + } if (browserContainer) { gZenUIManager.motion @@ -1615,6 +1621,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { ) .then(() => { this._maybeRemoveFakeBrowser(false); + this._finishAllAnimatingPromise = null; }); } return true; From ee91ea86ff5c34493d48be604ba2c83727b8fdb5 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Fri, 7 Mar 2025 18:53:45 +0100 Subject: [PATCH 067/127] Enhance ZenViewSplitter to support dynamic side detection for split view animations --- .../base/content/zen-styles/zen-decks.css | 4 ++ .../base/zen-components/ZenViewSplitter.mjs | 53 ++++++++++++++----- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-decks.css b/src/browser/base/content/zen-styles/zen-decks.css index 96e6237dc..c63b945c8 100644 --- a/src/browser/base/content/zen-styles/zen-decks.css +++ b/src/browser/base/content/zen-styles/zen-decks.css @@ -276,6 +276,10 @@ box-shadow: var(--zen-big-shadow); overflow: hidden; + &[side='right'] { + right: 0; + } + &::after { content: ''; position: absolute; diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index ac43a7c56..200976181 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -196,17 +196,20 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { if (currentView?.tabs.length >= this.MAX_TABS) { return; } - // only show if we are 1/4 of the way to the edge const panelsRect = gBrowser.tabbox.getBoundingClientRect(); const panelsWidth = panelsRect.width; if ( - event.clientX > panelsWidth / 2 || + event.clientX > panelsRect.left + panelsWidth - 10 || event.clientX < panelsRect.left + 10 || event.clientY < panelsRect.top + 10 || event.clientY > panelsRect.bottom - 10 ) { return; } + // first quarter or last quarter of the screen, but not the middle + if (!(event.clientX < panelsRect.left + panelsWidth / 4 || event.clientX > panelsRect.left + (panelsWidth / 4) * 3)) { + return; + } const oldTab = this._lastOpenedTab; this._canDrop = true; // wait some time before showing the split view @@ -219,6 +222,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { } const panelsWidth = gBrowser.tabbox.getBoundingClientRect().width; const halfWidth = panelsWidth / 2; + const side = event.clientX > halfWidth ? 'right' : 'left'; this.fakeBrowser = document.createXULElement('vbox'); this.fakeBrowser.addEventListener('dragleave', this.onBrowserDragEndToSplit); const padding = Services.prefs.getIntPref('zen.theme.content-element-separation', 0); @@ -227,14 +231,21 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { gBrowser.tabbox.appendChild(this.fakeBrowser); this.fakeBrowser.style.setProperty('--zen-split-view-fake-icon', `url(${draggedTab.getAttribute('image')})`); draggedTab._visuallySelected = true; + this.fakeBrowser.setAttribute('side', side); this._finishAllAnimatingPromise = Promise.all([ gZenUIManager.motion.animate( gBrowser.tabbox, + side === 'left' + ? { + paddingLeft: [0, `${halfWidth}px`], + paddingRight: 0, + } + : { + paddingRight: [0, `${halfWidth}px`], + paddingLeft: 0, + }, { - paddingLeft: [0, `${halfWidth}px`], - }, - { - duration: 0.15, + duration: 0.1, easing: 'ease-out', } ), @@ -242,10 +253,14 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { this.fakeBrowser, { width: [0, `${halfWidth - padding}px`], - marginLeft: [0, `${-halfWidth}px`], + ...(side === 'left' + ? { + marginLeft: [0, `${-halfWidth}px`], + } + : {}), }, { - duration: 0.15, + duration: 0.1, easing: 'ease-out', } ), @@ -289,15 +304,20 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { return; } this.fakeBrowser.classList.add('fade-out'); + const side = this.fakeBrowser.getAttribute('side'); gBrowser.selectedTab = this._draggingTab; this._draggingTab = null; try { Promise.all([ gZenUIManager.motion.animate( gBrowser.tabbox, - { - paddingLeft: [`${halfWidth}px`, 0], - }, + side === 'left' + ? { + paddingLeft: [`${halfWidth}px`, 0], + } + : { + paddingRight: [`${halfWidth}px`, 0], + }, { duration: 0.15, easing: 'ease-out', @@ -307,7 +327,11 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { this.fakeBrowser, { width: [`${halfWidth - padding * 2}px`, 0], - marginLeft: [`${-(halfWidth - padding)}px`, 0], + ...(side === 'left' + ? { + marginLeft: [`${-halfWidth}px`, 0], + } + : {}), }, { duration: 0.15, @@ -1521,6 +1545,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { return false; } + const dropSide = this.fakeBrowser?.getAttribute('side'); const containerRect = this.fakeBrowser.getBoundingClientRect(); const padding = Services.prefs.getIntPref('zen.theme.content-element-separation', 0); const dropTarget = document.elementFromPoint(containerRect.left + containerRect.width + padding + 5, event.clientY); @@ -1543,7 +1568,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { // Calculate which side of the target browser the drop occurred // const browserRect = browser.getBoundingClientRect(); // const hoverSide = this.calculateHoverSide(event.clientX, event.clientY, browserRect); - const hoverSide = 'left'; + const hoverSide = dropSide; if (droppedOnTab.splitView) { // Add to existing split view @@ -1595,7 +1620,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { //} // Put tabs always as if it was dropped from the left - this.splitTabs([draggedTab, droppedOnTab], gridType, 1); + this.splitTabs(dropSide == 'left' ? [draggedTab, droppedOnTab] : [droppedOnTab, draggedTab], gridType, 1); } } if (this._finishAllAnimatingPromise) { From 9a27b66661f46edcada63bd9a4eb14f61b20e390 Mon Sep 17 00:00:00 2001 From: Samuel <36420837+Samueru-sama@users.noreply.github.com> Date: Fri, 7 Mar 2025 14:03:52 -0400 Subject: [PATCH 068/127] remove unnecesary declation of several variables Signed-off-by: Samuel <36420837+Samueru-sama@users.noreply.github.com> --- AppDir/AppRun | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/AppDir/AppRun b/AppDir/AppRun index 523d60514..5a6c5706d 100644 --- a/AppDir/AppRun +++ b/AppDir/AppRun @@ -1,15 +1,6 @@ #!/bin/sh -SELF=$(readlink -f "$0") -HERE=${SELF%/*} -export PATH="${HERE}:${HERE}/usr/bin/:${HERE}/usr/sbin/:${HERE}/usr/games/:${HERE}/bin/:${HERE}/sbin/${PATH:+:$PATH}" -export LD_LIBRARY_PATH="${HERE}/usr/lib/:${HERE}/usr/lib/i386-linux-gnu/:${HERE}/usr/lib/x86_64-linux-gnu/:${HERE}/usr/lib32/:${HERE}/usr/lib64/:${HERE}/lib/:${HERE}/lib/i386-linux-gnu/:${HERE}/lib/x86_64-linux-gnu/:${HERE}/lib32/:${HERE}/lib64/${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" -export PYTHONPATH="${HERE}/usr/share/pyshared/${PYTHONPATH:+:$PYTHONPATH}" +CURRENTDIR="$(dirname "$(readlink -f "$0")")" +export PATH="${CURRENTDIR}:${PATH}" export MOZ_LEGACY_PROFILES=1 # Prevent per installation profiles -DEFAULT_XDG_DATA_DIRS='./share/:/usr/share/gnome:/usr/local/share/:/usr/share/' -export XDG_DATA_DIRS="${HERE}/usr/share/:${XDG_DATA_DIRS:-$DEFAULT_XDG_DATA_DIRS}" -export PERLLIB="${HERE}/usr/share/perl5/:${HERE}/usr/lib/perl5/${PERLLIB:+:$PERLLIB}" -export GSETTINGS_SCHEMA_DIR="${HERE}/usr/share/glib-2.0/schemas/${GSETTINGS_SCHEMA_DIR:+:$GSETTINGS_SCHEMA_DIR}" -export MOZ_APP_LAUNCHER="${APPIMAGE}" -export QT_PLUGIN_PATH="${HERE}/usr/lib/qt4/plugins/:${HERE}/usr/lib/i386-linux-gnu/qt4/plugins/:${HERE}/usr/lib/x86_64-linux-gnu/qt4/plugins/:${HERE}/usr/lib32/qt4/plugins/:${HERE}/usr/lib64/qt4/plugins/:${HERE}/usr/lib/qt5/plugins/:${HERE}/usr/lib/i386-linux-gnu/qt5/plugins/:${HERE}/usr/lib/x86_64-linux-gnu/qt5/plugins/:${HERE}/usr/lib32/qt5/plugins/:${HERE}/usr/lib64/qt5/plugins/${QT_PLUGIN_PATH:+:$QT_PLUGIN_PATH}" -EXEC=$(grep -e '^Exec=.*' "${HERE}"/*.desktop | head -n 1 | cut -d "=" -f 2 | cut -d " " -f 1) -exec "${EXEC}" "$@" +export MOZ_APP_LAUNCHER="${APPIMAGE}" # Allows setting as default browser +exec "${CURRENTDIR}/zen" "$@" From 2e21bcc54210c94a36d04df24728d7f462287051 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Fri, 7 Mar 2025 23:28:04 +0100 Subject: [PATCH 069/127] Enhance sidebar and vertical tab styles with workspace-specific adjustments --- .../content/zen-styles/zen-sidebar-panels.css | 1 + .../zen-styles/zen-tabs/vertical-tabs.css | 8 +- .../tabbrowser/content/tabbrowser-js.patch | 12 +-- .../tabbrowser/content/tabs-js.patch | 86 ++++++++++--------- 4 files changed, 60 insertions(+), 47 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-sidebar-panels.css b/src/browser/base/content/zen-styles/zen-sidebar-panels.css index fe9cfd792..da116f8df 100644 --- a/src/browser/base/content/zen-styles/zen-sidebar-panels.css +++ b/src/browser/base/content/zen-styles/zen-sidebar-panels.css @@ -111,6 +111,7 @@ background: transparent; border: none; cursor: ew-resize; + z-index: 2; &:is(.zen-split-view-splitter[orient='vertical']) { /* Bit of a hacky solution, but it works */ diff --git a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css index 0f9982a22..58e9b2114 100644 --- a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css +++ b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css @@ -373,8 +373,12 @@ overflow-y: auto; height: 100%; scrollbar-width: thin; - margin-left: calc(-1 * var(--zen-toolbox-padding)); - width: calc(100% + var(--zen-toolbox-padding) * 2); + + /* Only do this hack if we have workspaces enabled */ + :root[zen-workspace-id] & { + margin-left: calc(-1 * var(--zen-toolbox-padding)); + width: calc(100% + var(--zen-toolbox-padding) * 2); + } } #zen-browser-tabs-container { diff --git a/src/browser/components/tabbrowser/content/tabbrowser-js.patch b/src/browser/components/tabbrowser/content/tabbrowser-js.patch index 685b89576..261f98a20 100644 --- a/src/browser/components/tabbrowser/content/tabbrowser-js.patch +++ b/src/browser/components/tabbrowser/content/tabbrowser-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js -index 628aa6596627c85efe361fc1ece8fd58f7ee653e..10960c3fb00a00dcdcc2e2658ebff24f25d2514c 100644 +index 628aa6596627c85efe361fc1ece8fd58f7ee653e..c62727bad57eda3b9d9a73c1df739a92f194f0c2 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js @@ -412,11 +412,50 @@ @@ -352,16 +352,16 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..10960c3fb00a00dcdcc2e2658ebff24f tab.toggleAttribute("pinned", true); this.tabContainer._invalidateCachedTabs(); // Then ensure all the tab open/pinning information is sent. -@@ -3503,6 +3625,9 @@ - let leftoverTab = this.selectedTab; +@@ -3504,6 +3626,9 @@ this.selectedTab = tabToSelect; this.removeTab(leftoverTab); -+ } -+ else { -+ this.selectedTab._possibleEmptyTab = true; } ++ else { ++ this.selectedTab._possibleEmptyTab = true; // Not needed, but just in case. ++ } if (tabs.length > 1 || !tabs[0].selected) { + this._updateTabsAfterInsert(); @@ -3693,7 +3818,7 @@ // Ensure we have an index if one was not provided. if (typeof index != "number") { diff --git a/src/browser/components/tabbrowser/content/tabs-js.patch b/src/browser/components/tabbrowser/content/tabs-js.patch index 4c3e69d98..7185fe630 100644 --- a/src/browser/components/tabbrowser/content/tabs-js.patch +++ b/src/browser/components/tabbrowser/content/tabs-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js -index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a840ea19b 100644 +index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620036896db 100644 --- a/browser/components/tabbrowser/content/tabs.js +++ b/browser/components/tabbrowser/content/tabs.js @@ -94,7 +94,7 @@ @@ -11,7 +11,15 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a } return true; }; -@@ -339,7 +339,7 @@ +@@ -135,6 +135,7 @@ + this.previewPanel = null; + + this.allTabs[0].label = this.emptyTabTitle; ++ this.allTabs[0]._possibleEmptyTab = true; + + // Hide the secondary text for locales where it is unsupported due to size constraints. + const language = Services.locale.appLocaleAsBCP47; +@@ -339,7 +340,7 @@ // and we're not hitting the scroll buttons. if ( event.button != 0 || @@ -20,7 +28,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a event.composedTarget.localName == "toolbarbutton" ) { return; -@@ -388,6 +388,7 @@ +@@ -388,6 +389,7 @@ // Reset the "ignored click" flag target._ignoredCloseButtonClicks = false; } @@ -28,7 +36,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a } /* Protects from close-tab-button errant doubleclick: -@@ -683,7 +684,7 @@ +@@ -683,7 +685,7 @@ if (this.#isContainerVerticalPinnedExpanded(tab)) { // In expanded vertical mode, the max number of pinned tabs per row is dynamic // Set this before adjusting dragged tab's position @@ -37,7 +45,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a let tabsPerRow = 0; let position = 0; for (let pinnedTab of pinnedTabs) { -@@ -883,6 +884,10 @@ +@@ -883,6 +885,10 @@ } let draggedTab = event.dataTransfer.mozGetDataAt(TAB_DROP_TYPE, 0); @@ -48,7 +56,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a if ( (effects == "move" || effects == "copy") && this == draggedTab.container && -@@ -996,6 +1001,14 @@ +@@ -996,6 +1002,14 @@ this._tabDropIndicator.hidden = true; event.stopPropagation(); @@ -63,7 +71,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a if (draggedTab && dropEffect == "copy") { // copy the dropped tab (wherever it's from) let newIndex = this._getDropIndex(event); -@@ -1034,10 +1047,11 @@ +@@ -1034,10 +1048,11 @@ } } else { let pinned = draggedTab.pinned; @@ -79,7 +87,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a ); let size = this.verticalMode ? "height" : "width"; let screenAxis = this.verticalMode ? "screenY" : "screenX"; -@@ -1114,7 +1128,7 @@ +@@ -1114,7 +1129,7 @@ let postTransitionCleanup = () => { tab.removeAttribute("tabdrop-samewindow"); @@ -88,7 +96,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a if (dropIndex !== false) { gBrowser.moveTabTo(tab, dropIndex); if (!directionForward) { -@@ -1122,7 +1136,7 @@ +@@ -1122,7 +1137,7 @@ } } }; @@ -97,7 +105,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a postTransitionCleanup(); } else { let onTransitionEnd = transitionendEvent => { -@@ -1249,7 +1263,7 @@ +@@ -1249,7 +1264,7 @@ return; } } @@ -106,7 +114,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a gBrowser.loadTabs(urls, { inBackground, replace, -@@ -1279,13 +1293,23 @@ +@@ -1279,13 +1294,23 @@ return; } @@ -132,7 +140,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a ) { delete draggedTab._dragData; return; -@@ -1517,7 +1541,7 @@ +@@ -1517,7 +1542,7 @@ } get newTabButton() { @@ -141,7 +149,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a } get verticalMode() { -@@ -1537,28 +1561,40 @@ +@@ -1537,28 +1562,40 @@ if (this.#allTabs) { return this.#allTabs; } @@ -190,7 +198,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a return children.filter(node => node.tagName == "tab-group"); } -@@ -1579,7 +1615,7 @@ +@@ -1579,7 +1616,7 @@ */ get visibleTabs() { if (!this.#visibleTabs) { @@ -199,7 +207,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a } return this.#visibleTabs; } -@@ -1613,10 +1649,8 @@ +@@ -1613,10 +1650,8 @@ return this.#focusableItems; } @@ -212,7 +220,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a let focusableItems = []; for (let child of children) { -@@ -1632,6 +1666,7 @@ +@@ -1632,6 +1667,7 @@ } this.#focusableItems = [ @@ -220,7 +228,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a ...verticalPinnedTabsContainer.children, ...focusableItems, ]; -@@ -1642,6 +1677,7 @@ +@@ -1642,6 +1678,7 @@ _invalidateCachedTabs() { this.#allTabs = null; this._invalidateCachedVisibleTabs(); @@ -228,7 +236,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a } _invalidateCachedVisibleTabs() { -@@ -1656,8 +1692,8 @@ +@@ -1656,8 +1693,8 @@ #isContainerVerticalPinnedExpanded(tab) { return ( this.verticalMode && @@ -239,7 +247,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a ); } -@@ -1672,7 +1708,7 @@ +@@ -1672,7 +1709,7 @@ if (node == null) { // We have a container for non-tab elements at the end of the scrollbox. @@ -248,7 +256,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a } node.before(tab); -@@ -1772,7 +1808,7 @@ +@@ -1772,7 +1809,7 @@ // There are separate "new tab" buttons for horizontal tabs toolbar, vertical tabs and // for when the tab strip is overflowed (which is shared by vertical and horizontal tabs); // Attach the long click popup to all of them. @@ -257,7 +265,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a const newTab2 = this.newTabButton; const newTabVertical = document.getElementById( "vertical-tabs-newtab-button" -@@ -1855,7 +1891,7 @@ +@@ -1855,7 +1892,7 @@ let rect = ele => { return window.windowUtils.getBoundsWithoutFlushing(ele); }; @@ -266,7 +274,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a if (tab && rect(tab).width <= this._tabClipWidth) { this.setAttribute("closebuttons", "activetab"); } else { -@@ -1867,10 +1903,12 @@ +@@ -1867,10 +1904,12 @@ _handleTabSelect(aInstant) { let selectedTab = this.selectedItem; @@ -279,7 +287,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a selectedTab._notselectedsinceload = false; } -@@ -1882,7 +1920,7 @@ +@@ -1882,7 +1921,7 @@ return; } @@ -288,7 +296,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a if (!tabs.length) { return; } -@@ -1918,7 +1956,7 @@ +@@ -1918,7 +1957,7 @@ if (isEndTab && !this._hasTabTempMaxWidth) { return; } @@ -297,7 +305,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a // Force tabs to stay the same width, unless we're closing the last tab, // which case we need to let them expand just enough so that the overall // tabbar width is the same. -@@ -1933,7 +1971,7 @@ +@@ -1933,7 +1972,7 @@ let tabsToReset = []; for (let i = numPinned; i < tabs.length; i++) { let tab = tabs[i]; @@ -306,7 +314,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a if (!isEndTab) { // keep tabs the same width tab.style.transition = "none"; -@@ -1999,16 +2037,15 @@ +@@ -1999,16 +2038,15 @@ // Move pinned tabs to another container when the tabstrip is toggled to vertical // and when session restore code calls _positionPinnedTabs; update styling whenever // the number of pinned tabs changes. @@ -329,7 +337,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a } } -@@ -2016,9 +2053,7 @@ +@@ -2016,9 +2054,7 @@ } _resetVerticalPinnedTabs() { @@ -340,7 +348,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a if (!verticalTabsContainer.children.length) { return; -@@ -2031,8 +2066,8 @@ +@@ -2031,8 +2067,8 @@ } _positionPinnedTabs() { @@ -351,7 +359,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a let absPositionHorizontalTabs = this.overflowing && tabs.length > numPinned && numPinned > 0; -@@ -2041,7 +2076,7 @@ +@@ -2041,7 +2077,7 @@ if (this.verticalMode) { this._updateVerticalPinnedTabs(); @@ -360,7 +368,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a let layoutData = this._pinnedTabsLayoutCache; let uiDensity = document.documentElement.getAttribute("uidensity"); if (!layoutData || layoutData.uiDensity != uiDensity) { -@@ -2113,7 +2148,7 @@ +@@ -2113,7 +2149,7 @@ return; } @@ -369,7 +377,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a let directionX = screenX > dragData.animLastScreenX; let directionY = screenY > dragData.animLastScreenY; -@@ -2121,7 +2156,7 @@ +@@ -2121,7 +2157,7 @@ dragData.animLastScreenX = screenX; let { width: tabWidth, height: tabHeight } = @@ -378,7 +386,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a let shiftSizeX = tabWidth * movingTabs.length; let shiftSizeY = tabHeight; dragData.tabWidth = tabWidth; -@@ -2296,10 +2331,11 @@ +@@ -2296,10 +2332,11 @@ } let pinned = draggedTab.pinned; @@ -394,7 +402,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a ); if (this.#rtlMode) { -@@ -2348,7 +2384,11 @@ +@@ -2348,7 +2385,11 @@ translate = Math.min(Math.max(translate, firstBound), lastBound); for (let tab of movingTabs) { @@ -407,7 +415,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a } dragData.translatePos = translate; -@@ -2484,12 +2524,16 @@ +@@ -2484,12 +2525,16 @@ // Shift background tabs to leave a gap where the dragged tab // would currently be dropped. for (let tab of tabs) { @@ -425,7 +433,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a if (tab.group?.tabs[0] == tab) { tab.group.style.setProperty( "--tabgroup-dragover-transform", -@@ -2541,8 +2585,9 @@ +@@ -2541,8 +2586,9 @@ ); } @@ -437,7 +445,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a return; } -@@ -2553,6 +2598,7 @@ +@@ -2553,6 +2599,7 @@ tab.style.transform = ""; if (tab.group) { tab.group.style.removeProperty("--tabgroup-dragover-transform"); @@ -445,7 +453,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a } tab.removeAttribute("dragover-createGroup"); } -@@ -2604,7 +2650,7 @@ +@@ -2604,7 +2651,7 @@ movingTab._moveTogetherSelectedTabsData.newIndex = movingTabNewIndex; movingTab._moveTogetherSelectedTabsData.animate = false; }; @@ -454,7 +462,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a postTransitionCleanup(); } else { let onTransitionEnd = transitionendEvent => { -@@ -2707,9 +2753,9 @@ +@@ -2707,9 +2754,9 @@ function newIndex(aTab, index) { // Don't allow mixing pinned and unpinned tabs. if (aTab.pinned) { @@ -466,7 +474,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..a2a0ca3982634252abfdad20e768431a } } -@@ -2793,7 +2839,7 @@ +@@ -2793,7 +2840,7 @@ } _notifyBackgroundTab(aTab) { From ff339c3fb022ae34d0b739842db828b11a180a8c Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sat, 8 Mar 2025 02:01:04 +0100 Subject: [PATCH 070/127] Update @zen-browser/surfer dependency to version 1.9.20 --- package-lock.json | 14 +- package.json | 2 +- pnpm-lock.yaml | 1916 --------------------------------------------- 3 files changed, 8 insertions(+), 1924 deletions(-) delete mode 100644 pnpm-lock.yaml diff --git a/package-lock.json b/package-lock.json index 6efdd3b9d..cb00ed74d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@zen-browser/surfer": "^1.9.19" + "@zen-browser/surfer": "^1.9.20" }, "devDependencies": { "husky": "^9.1.7", @@ -270,9 +270,9 @@ "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" }, "node_modules/@zen-browser/surfer": { - "version": "1.9.19", - "resolved": "https://registry.npmjs.org/@zen-browser/surfer/-/surfer-1.9.19.tgz", - "integrity": "sha512-EFZC1ZgU/vFU5AUFxjGxkXbekSbqFS5r1jV8s55QJa+ieU2ZdgFr7OO8wTQ/jyN0we+QK1ILdFCEpdGLBOpRmw==", + "version": "1.9.20", + "resolved": "https://registry.npmjs.org/@zen-browser/surfer/-/surfer-1.9.20.tgz", + "integrity": "sha512-/ZV0+UMg/ZpiyLCtNrIrsU8MELTFinQNRz83lOflImygiRo9eNdv4SqWwuSSTMxBqUzwa3xGiw9dCUYq/QFK5g==", "dependencies": { "@resvg/resvg-js": "^1.4.0", "async-icns": "^1.0.2", @@ -2810,9 +2810,9 @@ "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" }, "@zen-browser/surfer": { - "version": "1.9.19", - "resolved": "https://registry.npmjs.org/@zen-browser/surfer/-/surfer-1.9.19.tgz", - "integrity": "sha512-EFZC1ZgU/vFU5AUFxjGxkXbekSbqFS5r1jV8s55QJa+ieU2ZdgFr7OO8wTQ/jyN0we+QK1ILdFCEpdGLBOpRmw==", + "version": "1.9.20", + "resolved": "https://registry.npmjs.org/@zen-browser/surfer/-/surfer-1.9.20.tgz", + "integrity": "sha512-/ZV0+UMg/ZpiyLCtNrIrsU8MELTFinQNRz83lOflImygiRo9eNdv4SqWwuSSTMxBqUzwa3xGiw9dCUYq/QFK5g==", "requires": { "@resvg/resvg-js": "^1.4.0", "async-icns": "^1.0.2", diff --git a/package.json b/package.json index 91d2afd4c..ad56c7a58 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ }, "homepage": "https://github.com/zen-browser/core#readme", "dependencies": { - "@zen-browser/surfer": "^1.9.19" + "@zen-browser/surfer": "^1.9.20" }, "devDependencies": { "husky": "^9.1.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml deleted file mode 100644 index a05c0dac3..000000000 --- a/pnpm-lock.yaml +++ /dev/null @@ -1,1916 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - dependencies: - '@zen-browser/surfer': - specifier: ^1.9.16 - version: 1.9.16(glob@7.2.3) - devDependencies: - husky: - specifier: ^9.1.7 - version: 9.1.7 - lint-staged: - specifier: ^15.3.0 - version: 15.3.0 - prettier: - specifier: ^3.4.2 - version: 3.4.2 - prettier-plugin-sh: - specifier: ^0.14.0 - version: 0.14.0(prettier@3.4.2) - -packages: - - '@oozcitak/dom@1.15.10': - resolution: {integrity: sha512-0JT29/LaxVgRcGKvHmSrUTEvZ8BXvZhGl2LASRUgHqDTC1M5g1pLmVv56IYNyt3bG2CUjDkc67wnyZC14pbQrQ==} - engines: {node: '>=8.0'} - - '@oozcitak/infra@1.0.8': - resolution: {integrity: sha512-JRAUc9VR6IGHOL7OGF+yrvs0LO8SlqGnPAMqyzOuFZPSZSXI7Xf2O9+awQPSMXgIWGtgUf/dA6Hs6X6ySEaWTg==} - engines: {node: '>=6.0'} - - '@oozcitak/url@1.0.4': - resolution: {integrity: sha512-kDcD8y+y3FCSOvnBI6HJgl00viO/nGbQoCINmQ0h98OhnGITrWR3bOGfwYCthgcrV8AnTJz8MzslTQbC3SOAmw==} - engines: {node: '>=8.0'} - - '@oozcitak/util@8.3.8': - resolution: {integrity: sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ==} - engines: {node: '>=8.0'} - - '@resvg/resvg-js-android-arm-eabi@1.4.0': - resolution: {integrity: sha512-8C7P2dYNeL5mghCgJ+2IqNwv5V50d5pZQYIvGYlbP7d3OB/T8uVEcmuflYgWq+/vEn1gZE+Q2A0tFJOHqIvH9A==} - engines: {node: '>= 10'} - cpu: [arm] - os: [android] - - '@resvg/resvg-js-android-arm64@1.4.0': - resolution: {integrity: sha512-BQp3zo+/8Ns9u2NCh7YeII2KflsiXfJDrwahXk21PuDp0l1KcMjdQ2o4dTWTskF5Dba/rcuDa94T5GD9Pgap7g==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [android] - - '@resvg/resvg-js-darwin-arm64@1.4.0': - resolution: {integrity: sha512-IuvUOIpdxk5fEqr8EXgdCfugRWS88HlXwSeHPDVNCh/9kQ7exRoVi5CDOipkngUPYKxbKTekJWTxQHRUtf8oNQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - - '@resvg/resvg-js-darwin-x64@1.4.0': - resolution: {integrity: sha512-XFao3tkBBPHubVvXDX/ViYf2509tgqcfUc6bDtVYHCUOecK10ppbtdMRRnXjesi3towPQj2peiRUEavTIBbfGg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - - '@resvg/resvg-js-linux-arm-gnueabihf@1.4.0': - resolution: {integrity: sha512-RAjGdBJKGO5tSE1PsTl2WpG/TkgJGqsHIFtaQAUWNG4/LQ+0MNAptBOGrvNZvmRu+hVIk1t8m9rKme2RMdmlLQ==} - engines: {node: '>= 10'} - cpu: [arm] - os: [linux] - - '@resvg/resvg-js-linux-arm64-gnu@1.4.0': - resolution: {integrity: sha512-mT0UWGyzSaTu48sJGQno9zaZqk7j9ZjZppNu/TkLqObYu0xSeTnxnU73/Xy+byZh9RvLY/994bEaOP50jpDW/g==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@resvg/resvg-js-linux-arm64-musl@1.4.0': - resolution: {integrity: sha512-wfl0dk9pNExJeFxRoAO0P0ywVkqW80FqsCH6KCtTbB1f2P2NY0paAKPho1LJ2z1YSzq3ngganyAKPl2PoBqn4g==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@resvg/resvg-js-linux-x64-gnu@1.4.0': - resolution: {integrity: sha512-XDebImgHmQMIjxISZ4UsV9iHcO2IJnkKrT9/F5SWF3MgqRLro2pIY1JsgW70sEjkHlcyF7dbTa/M7TAgSz0uvg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@resvg/resvg-js-linux-x64-musl@1.4.0': - resolution: {integrity: sha512-cvq7pPQECLyP5SoI5ECZL0RhKcgz7sQTjYWQdZjFdF6riN40uWSo1Le31+oLLCwSoSOo8Z60xmU95ChbZjSY5Q==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@resvg/resvg-js-win32-arm64-msvc@1.4.0': - resolution: {integrity: sha512-4waye03doDRsQmtibxiTQ7alAmvT2D7gt5n3gmIMsAP8fF+szRQ+cD/ClPZdBIMonhAUbe3nLMduocOe2Jp59Q==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - - '@resvg/resvg-js-win32-ia32-msvc@1.4.0': - resolution: {integrity: sha512-9Ld/Hv8nXslvodPv9wL3wec8Tf9kFAO4t9632Y66aAcGZBNW/xAwzbgDOSv32N763tsLphleu1DhJ7nXKZIz9A==} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - - '@resvg/resvg-js-win32-x64-msvc@1.4.0': - resolution: {integrity: sha512-sMGQdOIop6a/s+cmFodnQNNykvr/MavgBXCzVt9jp1Rq4PXWtn8uwSsUupsn3SHPJCZ83kee6m4JCnak6Rec9A==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - - '@resvg/resvg-js@1.4.0': - resolution: {integrity: sha512-AcsRqAPFMIOxlMZCHxSxTG5vZTbW95xFDrQDTmsX/VEwc3tgLL9E4Be2nIJjWrdvIQxsTlaWYJsn2pxkki9Ltg==} - engines: {node: '>= 10'} - - '@types/node@17.0.45': - resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} - - '@zen-browser/surfer@1.9.16': - resolution: {integrity: sha512-6/Vcp1Ox9mt53hoBUuxFvpnRMnlvjFb3GBOcRhpqoYW/yi9mlV3G48icE717wGCoR2TThfuS6SYVfiT/G1kkrw==} - hasBin: true - - ansi-escapes@7.0.0: - resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} - engines: {node: '>=18'} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-regex@6.1.0: - resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} - engines: {node: '>=12'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - - argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - - asap@2.0.6: - resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} - - async-compat@1.6.8: - resolution: {integrity: sha512-MVKdync5q2FgE+x/AErx0mtJSZgQxWBGIx7vOcQbXmTh04OAF41N2zQX5XhAb0Mq/sMSFqzZSSFwzZ3rrROsSg==} - engines: {node: '>=0.8'} - - async-icns@1.0.2: - resolution: {integrity: sha512-d2P/f3aAWdOE3+tEqTW4HLj9Ob7/t54/NH2nRFK9Q7ZhJJXK7TlF1G3vgB6UP/ILHjI3Akjv+d8sFXyAZxCIFQ==} - hasBin: true - - axios@0.21.4: - resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - base64-js@0.0.2: - resolution: {integrity: sha512-Pj9L87dCdGcKlSqPVUjD+q96pbIx1zQQLb2CUiWURfjiBELv84YX+0nGnKmyT/9KkC7PQk7UN1w+Al8bBozaxQ==} - engines: {node: '>= 0.4'} - - base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - - bl@2.2.1: - resolution: {integrity: sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==} - - bl@3.0.1: - resolution: {integrity: sha512-jrCW5ZhfQ/Vt07WX1Ngs+yn9BDqPL/gw28S7s9H6QK/gupnizNzJAss5akW20ISgOrbLTlXOOCTJeNUQqruAWQ==} - - bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - - bops@0.1.1: - resolution: {integrity: sha512-Cx1zStcMp+YoFan8OgudNPMih82eJZE+27feki1WeyoFTR9Ye7AR1SUW3saE6QQvdS/g52aJ2IojBjWOiRiLbw==} - - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - - buffer-alloc-unsafe@1.1.0: - resolution: {integrity: sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==} - - buffer-alloc@1.2.0: - resolution: {integrity: sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==} - - buffer-fill@1.0.0: - resolution: {integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==} - - buffer-v6-polyfill@1.0.5: - resolution: {integrity: sha512-LdUw/JMZyKN+EBDbOHqynYtOLXDjgo+uf5vCUhfO5hVsU2chvbqyexizvxUMaU4ipYZy9MiQyIFwMeIgsb6nBA==} - - buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - - call-once-fn@1.0.15: - resolution: {integrity: sha512-LPMeZc0iO4Ep9XCtvRk9ecOdQpJd1DKRWly1+95F+OinTRJri39ZUVItxJu0ru/KzBbbv0cmKFb0gzG4PJCinA==} - engines: {node: '>=0.8'} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - chalk@5.4.1: - resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - - chownr@1.1.4: - resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} - - cli-cursor@5.0.0: - resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} - engines: {node: '>=18'} - - cli-progress@3.12.0: - resolution: {integrity: sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==} - engines: {node: '>=4'} - - cli-truncate@4.0.0: - resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} - engines: {node: '>=18'} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - color-string@1.9.1: - resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} - - color@4.2.3: - resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} - engines: {node: '>=12.5.0'} - - colorette@2.0.20: - resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - - commander@12.1.0: - resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} - engines: {node: '>=18'} - - commander@6.2.1: - resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} - engines: {node: '>= 6'} - - commander@9.5.0: - resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} - engines: {node: ^12.20.0 || >=14} - - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - content-disposition@0.5.4: - resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} - engines: {node: '>= 0.6'} - - core-js-pure@3.40.0: - resolution: {integrity: sha512-AtDzVIgRrmRKQai62yuSIN5vNiQjcJakJb4fbhVw3ehxx7Lohphvw9SGNWKhLFqSxC4ilD0g/L1huAYFQU3Q6A==} - - core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - - cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} - - debug@4.4.0: - resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - decompress-response@6.0.0: - resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} - engines: {node: '>=10'} - - deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - - detect-libc@2.0.3: - resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} - engines: {node: '>=8'} - - duplexify@4.1.3: - resolution: {integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==} - - emoji-regex@10.4.0: - resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} - - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - end-of-stream@1.4.4: - resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} - - environment@1.1.0: - resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} - engines: {node: '>=18'} - - esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - - eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - - execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - - execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} - - expand-template@2.0.3: - resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} - engines: {node: '>=6'} - - extract-base-iterator@1.2.22: - resolution: {integrity: sha512-gGMzo6ijt6oh9VSLOG3H+rpyzkoCYkVBgF/qdxVM/Wc/eKJyX2gxrBN8gO7IbnAMxre36wvzwzzD6umw80i3CQ==} - engines: {node: '>=0.8'} - - fast-extract@1.3.31: - resolution: {integrity: sha512-P3poghIIxD7mEIHymqaeevrrdWD23JLyagIfox+/jw6r0L8CtjHJsg/S/YZsHH6V2/IfK5tHoBsiyAqBIocSHw==} - engines: {node: '>=0.8'} - peerDependencies: - lzma-native: '*' - peerDependenciesMeta: - lzma-native: - optional: true - - fifo@2.4.1: - resolution: {integrity: sha512-XTbUCNmo54Jav0hcL6VxDuY4x1eCQH61HEF80C2Oww283pfjQ2C8avZeyq4v43sW2S2403kmzssE9j4lbF66Sg==} - - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - - flush-write-stream@2.0.0: - resolution: {integrity: sha512-uXClqPxT4xW0lcdSBheb2ObVU+kuqUk3Jk64EwieirEXZx9XUrVwp/JuBfKAWaM4T5Td/VL7QLDWPXp/MvGm/g==} - - follow-redirects@1.15.9: - resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - - fs-constants@1.0.0: - resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - - fs-extra@10.1.0: - resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} - engines: {node: '>=12'} - - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - - get-east-asian-width@1.3.0: - resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} - engines: {node: '>=18'} - - get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - - get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} - - github-from-package@0.0.0: - resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} - - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - - globalyzer@0.1.0: - resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==} - - globrex@0.1.2: - resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} - - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - hash-string@1.0.0: - resolution: {integrity: sha512-dtNNyxXobzHavayZwOwRWhBTqS9GX4jDjIMsGc0fDyaN2A+4zMn5Ua9ODDCggN6w3Spma6mAHL3ImmW3BkWDmQ==} - - human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - - human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} - - husky@9.1.7: - resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} - engines: {node: '>=18'} - hasBin: true - - ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - - ini@3.0.1: - resolution: {integrity: sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - is-absolute@1.0.0: - resolution: {integrity: sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==} - engines: {node: '>=0.10.0'} - - is-apple-silicon@https://codeload.github.com/trickypr/is-apple-silicon/tar.gz/5f75501a1d7566ba9f94174b6825d7bd9d302b6a: - resolution: {tarball: https://codeload.github.com/trickypr/is-apple-silicon/tar.gz/5f75501a1d7566ba9f94174b6825d7bd9d302b6a} - version: 1.0.1 - - is-arrayish@0.3.2: - resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} - - is-error@2.2.2: - resolution: {integrity: sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg==} - - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - is-fullwidth-code-point@4.0.0: - resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} - engines: {node: '>=12'} - - is-fullwidth-code-point@5.0.0: - resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} - engines: {node: '>=18'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-promise@4.0.0: - resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} - - is-relative@1.0.0: - resolution: {integrity: sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==} - engines: {node: '>=0.10.0'} - - is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - - is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - is-unc-path@1.0.0: - resolution: {integrity: sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==} - engines: {node: '>=0.10.0'} - - is-windows@1.0.2: - resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} - engines: {node: '>=0.10.0'} - - isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true - - jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - - kleur@3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} - - kleur@4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} - - lifecycle@1.0.4: - resolution: {integrity: sha512-FJx0SNrM2rouctdOH4rATsHT+BvgyXX4LEQ+Yn9COQNPK3u4XAPp9qS7OKpRO22MeT39oxkjZkRcLnHxSmiduw==} - - lilconfig@3.1.3: - resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} - engines: {node: '>=14'} - - lint-staged@15.3.0: - resolution: {integrity: sha512-vHFahytLoF2enJklgtOtCtIjZrKD/LoxlaUusd5nh7dWv/dkKQJY74ndFSzxCdv7g0ueGg1ORgTSt4Y9LPZn9A==} - engines: {node: '>=18.12.0'} - hasBin: true - - listr2@8.2.5: - resolution: {integrity: sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==} - engines: {node: '>=18.0.0'} - - lodash.compact@3.0.1: - resolution: {integrity: sha512-2ozeiPi+5eBXW1CLtzjk8XQFhQOEMwwfxblqeq6EGyTxZJ1bPATqilY0e6g2SLQpP4KuMeuioBhEnWz5Pr7ICQ==} - - lodash.throttle@4.1.1: - resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} - - log-update@6.1.0: - resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} - engines: {node: '>=18'} - - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - - micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} - - mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - - mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - - mimic-function@5.0.1: - resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} - engines: {node: '>=18'} - - mimic-response@3.1.0: - resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} - engines: {node: '>=10'} - - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - mkdirp-classic@0.5.3: - resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} - - mock-require-lazy@1.0.14: - resolution: {integrity: sha512-PNuw/5/+IJLgOSJoXv4DYBu840i2NmhRFgUoB/To/hvL7J8YxjjrvNaAaPotq7Ndff344pDFSqDqGpstdhB8Tg==} - engines: {node: '>=0.8'} - - modern-async@1.1.5: - resolution: {integrity: sha512-Yioj6tw1jvZef+bYjcZN9gMPBpVkkqGOMbQg/1U9dIqdij44mpftvNJxTf/u2Gc6oobuNGUFWNJwJwq8qEs9bw==} - - mount-dmg@1.0.1: - resolution: {integrity: sha512-YEHSgtE1d6jIm6ht0uqo4MWQSXHvHYujgURXf+59hQDErH5bL5rv4uGwko8ejiFIeK6ySk8jBX1oX9NrlmBTCg==} - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - mvdan-sh@0.10.1: - resolution: {integrity: sha512-kMbrH0EObaKmK3nVRKUIIya1dpASHIEusM13S4V1ViHFuxuNxCo+arxoa6j/dbV22YBGjl7UKJm9QQKJ2Crzhg==} - - nanoassert@2.0.0: - resolution: {integrity: sha512-7vO7n28+aYO4J+8w96AzhmU8G+Y/xpPDJz/se19ICsqj/momRbb9mh9ZUtkoJ5X3nTnPdhEJyc0qnM6yAsHBaA==} - - napi-build-utils@2.0.0: - resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} - - next-tick@1.1.0: - resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} - - node-abi@3.73.0: - resolution: {integrity: sha512-z8iYzQGBu35ZkTQ9mtR8RqugJZ9RCLn8fv3d7LsgDBzOijGQP3RdKTX4LA7LXw03ZhU5z0l4xfhIMgSES31+cg==} - engines: {node: '>=10'} - - node-addon-api@5.1.0: - resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} - - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - - npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - - npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - - on-one@0.1.4: - resolution: {integrity: sha512-fWyHjSVZvs7Dkt7F/fZCm4Eoxv7+uQkaiUYh3jDVN15khYa5iTnFWW9VM8rQgStAca5cDxHzyAT7cF+gfyLgcg==} - engines: {node: '>=0.8'} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - - onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - - onetime@7.0.0: - resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} - engines: {node: '>=18'} - - os-shim@0.1.3: - resolution: {integrity: sha512-jd0cvB8qQ5uVt0lvCIexBaROw1KyKm5sbulg2fWOHjETisuCzWyt+eTZKEMs8v6HwzoGs8xik26jg7eCM6pS+A==} - engines: {node: '>= 0.4.0'} - - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - pidtree@0.6.0: - resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} - engines: {node: '>=0.10'} - hasBin: true - - png-to-ico@2.1.8: - resolution: {integrity: sha512-Nf+IIn/cZ/DIZVdGveJp86NG5uNib1ZXMiDd/8x32HCTeKSvgpyg6D/6tUBn1QO/zybzoMK0/mc3QRgAyXdv9w==} - engines: {node: '>=8'} - hasBin: true - - pngjs@6.0.0: - resolution: {integrity: sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==} - engines: {node: '>=12.13.0'} - - prebuild-install@7.1.3: - resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} - engines: {node: '>=10'} - hasBin: true - - prettier-plugin-sh@0.14.0: - resolution: {integrity: sha512-hfXulj5+zEl/ulrO5kMuuTPKmXvOg0bnLHY1hKFNN/N+/903iZbNp8NyZBTsgI8dtkSgFfAEIQq0IQTyP1ZVFQ==} - engines: {node: '>=16.0.0'} - peerDependencies: - prettier: ^3.0.3 - - prettier@3.4.2: - resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==} - engines: {node: '>=14'} - hasBin: true - - process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - - progress-stream@2.0.0: - resolution: {integrity: sha512-xJwOWR46jcXUq6EH9yYyqp+I52skPySOeHfkxOZ2IY1AiBi/sFJhbhAKHoV3OTw/omQ45KTio9215dRJ2Yxd3Q==} - - prompts@2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} - - pump@3.0.2: - resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} - - pumpify@2.0.1: - resolution: {integrity: sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==} - - queue-cb@1.4.16: - resolution: {integrity: sha512-7g8cAIeoENe4kYgLAjTF7j7nX71pLlGdIAViR8U8pmHD3UA116+LjMRyucE6c6qUYBlv4ppaYXCTZjlo/IN27w==} - engines: {node: '>=0.8'} - - rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true - - readable-stream@2.3.8: - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - - readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - - require_optional@1.0.1: - resolution: {integrity: sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==} - - resolve-from@2.0.0: - resolution: {integrity: sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==} - engines: {node: '>=0.10.0'} - - restore-cursor@5.1.0: - resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} - engines: {node: '>=18'} - - rfdc@1.4.1: - resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - - rimraf2@2.8.2: - resolution: {integrity: sha512-Bz7P3Zu6lEpek5LduIqg5A2mRu8kCllR+rGYofqq9bRRiHC9m+Py/EiINPt9iu/XOqQ//Q++XSka7EwL3K3Chw==} - hasBin: true - peerDependencies: - glob: '*' - peerDependenciesMeta: - glob: - optional: true - - rustic@1.2.2: - resolution: {integrity: sha512-aagYrcImcYj3QbaP7nirOw8/q8aULMu0LkKucP9B4WsRbXlXpk195nYAEB+uJzAcgk2pKS+yMzbAJtIoOqwZoQ==} - - safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - - semver@7.6.3: - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} - engines: {node: '>=10'} - hasBin: true - - sh-syntax@0.4.2: - resolution: {integrity: sha512-/l2UZ5fhGZLVZa16XQM9/Vq/hezGGbdHeVEA01uWjOL1+7Ek/gt6FquW0iKKws4a9AYPYvlz6RyVvjh3JxOteg==} - engines: {node: '>=16.0.0'} - - sharp@0.30.7: - resolution: {integrity: sha512-G+MY2YW33jgflKPTXXptVO28HvNOo9G3j0MybYAHeEmby+QuD2U98dT6ueht9cv/XDqZspSpIhoSW+BAKJ7Hig==} - engines: {node: '>=12.13.0'} - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - shell-escape@0.2.0: - resolution: {integrity: sha512-uRRBT2MfEOyxuECseCZd28jC1AJ8hmqqneWQ4VWUTgCAFvb3wKU1jLqj6egC4Exrr88ogg3dp+zroH4wJuaXzw==} - - short-hash@1.0.0: - resolution: {integrity: sha512-qbUCD2Pkl4IXRyVqneEjGnUr0NGDGLzZnBUVGJngIQZf/FrhOL0yJhH+JQzak0t8xMmScIKpoX1SxOsPHdwa4w==} - - signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - - simple-concat@1.0.1: - resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} - - simple-get@4.0.1: - resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} - - simple-swizzle@0.2.2: - resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} - - sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - - slice-ansi@5.0.0: - resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} - engines: {node: '>=12'} - - slice-ansi@7.1.0: - resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} - engines: {node: '>=18'} - - speedometer@1.0.0: - resolution: {integrity: sha512-lgxErLl/7A5+vgIIXsh9MbeukOaCb2axgQ+bKCdIE+ibNT4XNYGNCR1qFEGq6F+YDASXK3Fh/c5FgtZchFolxw==} - - sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - - stack-base-iterator@1.1.20: - resolution: {integrity: sha512-dlhhk0qesNjtXQCvJsayyvrUIh4gz6HkGC3g00RmXUgpbpYV7SJm97/Ac2HNUfO2mtq68DEGvt+msCf7Uk55Hg==} - engines: {node: '>=0.8'} - - stream-shift@1.0.3: - resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==} - - string-argv@0.3.2: - resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} - engines: {node: '>=0.6.19'} - - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - - string-width@7.2.0: - resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} - engines: {node: '>=18'} - - string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - - strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - - strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - - strip-json-comments@2.0.1: - resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} - engines: {node: '>=0.10.0'} - - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - - tar-fs@2.1.2: - resolution: {integrity: sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==} - - tar-iterator@1.2.25: - resolution: {integrity: sha512-PyjH/Rils3eQ2ThsBG4O8zQLx/nPkoS/Iqvob4wEtpOJoO5DcqQKeI88aGWC3ktG6ms1Lgf1qrYtCo59W4WeRg==} - engines: {node: '>=0.8'} - - tar-stream-compat@2.1.5: - resolution: {integrity: sha512-hhIcRHj6S+y7IDR+VO8IcOjPUsAJ+50POvGK1fDFqbOTLTs/J7YA07TUgvpSkYkYuRUfYsuAFM/0SrvrdIZMdQ==} - engines: {node: '>=0.8'} - - tar-stream@2.2.0: - resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} - engines: {node: '>=6'} - - temp-suffix@0.1.14: - resolution: {integrity: sha512-OqUZmSYtyGgteGxgjh8mkV69Zr1GXSYMj/+VUol698zxnopimbAlmIx5cQIIg1F9XDyA01htZfxLqC1FQZ7hbw==} - engines: {node: '>=0.8'} - - through2@2.0.5: - resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} - - through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - - tiny-glob@0.2.9: - resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} - - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - to-utf8@0.0.1: - resolution: {integrity: sha512-zks18/TWT1iHO3v0vFp5qLKOG27m67ycq/Y7a7cTiRuUNlc4gf3HGnkRgMv0NyhnfTamtkYBJl+YeD1/j07gBQ==} - - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - - tunnel-agent@0.6.0: - resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} - - unbzip2-stream@1.4.3: - resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} - - unc-path-regex@0.1.2: - resolution: {integrity: sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==} - engines: {node: '>=0.10.0'} - - universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - - util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - wrap-ansi@9.0.0: - resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} - engines: {node: '>=18'} - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - xmlbuilder2@3.1.1: - resolution: {integrity: sha512-WCSfbfZnQDdLQLiMdGUQpMxxckeQ4oZNMNhLVkcekTu7xhD4tuUDyAPoY8CwXvBYE6LwBHd6QW2WZXlOWr1vCw==} - engines: {node: '>=12.0'} - - xtend@4.0.2: - resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} - engines: {node: '>=0.4'} - - yaml@2.6.1: - resolution: {integrity: sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==} - engines: {node: '>= 14'} - hasBin: true - - zip-iterator@1.2.23: - resolution: {integrity: sha512-gS+3YsU/vIHXxaViw67Dm1DMyN7U5iVU/NFB0rWYKyN7MYlOH61icBZm8RWesDtknsUaT9saEChwj+ueZKS8Dg==} - engines: {node: '>=0.8'} - - zip@1.2.0: - resolution: {integrity: sha512-8B4Z9BXJKkI8BkHhKvQan4rwCzUENnj95YHFYrI7F1NbqKCIdW86kujctzEB+kJ6XapHPiAhiZ9xi5GbW5SPdw==} - -snapshots: - - '@oozcitak/dom@1.15.10': - dependencies: - '@oozcitak/infra': 1.0.8 - '@oozcitak/url': 1.0.4 - '@oozcitak/util': 8.3.8 - - '@oozcitak/infra@1.0.8': - dependencies: - '@oozcitak/util': 8.3.8 - - '@oozcitak/url@1.0.4': - dependencies: - '@oozcitak/infra': 1.0.8 - '@oozcitak/util': 8.3.8 - - '@oozcitak/util@8.3.8': {} - - '@resvg/resvg-js-android-arm-eabi@1.4.0': - optional: true - - '@resvg/resvg-js-android-arm64@1.4.0': - optional: true - - '@resvg/resvg-js-darwin-arm64@1.4.0': - optional: true - - '@resvg/resvg-js-darwin-x64@1.4.0': - optional: true - - '@resvg/resvg-js-linux-arm-gnueabihf@1.4.0': - optional: true - - '@resvg/resvg-js-linux-arm64-gnu@1.4.0': - optional: true - - '@resvg/resvg-js-linux-arm64-musl@1.4.0': - optional: true - - '@resvg/resvg-js-linux-x64-gnu@1.4.0': - optional: true - - '@resvg/resvg-js-linux-x64-musl@1.4.0': - optional: true - - '@resvg/resvg-js-win32-arm64-msvc@1.4.0': - optional: true - - '@resvg/resvg-js-win32-ia32-msvc@1.4.0': - optional: true - - '@resvg/resvg-js-win32-x64-msvc@1.4.0': - optional: true - - '@resvg/resvg-js@1.4.0': - optionalDependencies: - '@resvg/resvg-js-android-arm-eabi': 1.4.0 - '@resvg/resvg-js-android-arm64': 1.4.0 - '@resvg/resvg-js-darwin-arm64': 1.4.0 - '@resvg/resvg-js-darwin-x64': 1.4.0 - '@resvg/resvg-js-linux-arm-gnueabihf': 1.4.0 - '@resvg/resvg-js-linux-arm64-gnu': 1.4.0 - '@resvg/resvg-js-linux-arm64-musl': 1.4.0 - '@resvg/resvg-js-linux-x64-gnu': 1.4.0 - '@resvg/resvg-js-linux-x64-musl': 1.4.0 - '@resvg/resvg-js-win32-arm64-msvc': 1.4.0 - '@resvg/resvg-js-win32-ia32-msvc': 1.4.0 - '@resvg/resvg-js-win32-x64-msvc': 1.4.0 - - '@types/node@17.0.45': {} - - '@zen-browser/surfer@1.9.16(glob@7.2.3)': - dependencies: - '@resvg/resvg-js': 1.4.0 - async-icns: 1.0.2 - axios: 0.21.4 - chalk: 4.1.2 - cli-progress: 3.12.0 - commander: 6.2.1 - execa: 5.1.1 - fast-extract: 1.3.31(glob@7.2.3) - fs-extra: 10.1.0 - ini: 3.0.1 - is-apple-silicon: https://codeload.github.com/trickypr/is-apple-silicon/tar.gz/5f75501a1d7566ba9f94174b6825d7bd9d302b6a - kleur: 4.1.5 - modern-async: 1.1.5 - mount-dmg: 1.0.1 - picomatch: 2.3.1 - png-to-ico: 2.1.8 - prompts: 2.4.2 - rustic: 1.2.2 - semver: 7.6.3 - sharp: 0.30.7 - tiny-glob: 0.2.9 - xmlbuilder2: 3.1.1 - transitivePeerDependencies: - - debug - - glob - - lzma-native - - ansi-escapes@7.0.0: - dependencies: - environment: 1.1.0 - - ansi-regex@5.0.1: {} - - ansi-regex@6.1.0: {} - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - ansi-styles@6.2.1: {} - - argparse@1.0.10: - dependencies: - sprintf-js: 1.0.3 - - asap@2.0.6: {} - - async-compat@1.6.8: - dependencies: - is-error: 2.2.2 - is-promise: 4.0.0 - - async-icns@1.0.2: - dependencies: - commander: 9.5.0 - - axios@0.21.4: - dependencies: - follow-redirects: 1.15.9 - transitivePeerDependencies: - - debug - - balanced-match@1.0.2: - optional: true - - base64-js@0.0.2: {} - - base64-js@1.5.1: {} - - bl@2.2.1: - dependencies: - readable-stream: 2.3.8 - safe-buffer: 5.2.1 - - bl@3.0.1: - dependencies: - readable-stream: 3.6.2 - - bl@4.1.0: - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 - - bops@0.1.1: - dependencies: - base64-js: 0.0.2 - to-utf8: 0.0.1 - - brace-expansion@1.1.11: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - optional: true - - braces@3.0.3: - dependencies: - fill-range: 7.1.1 - - buffer-alloc-unsafe@1.1.0: {} - - buffer-alloc@1.2.0: - dependencies: - buffer-alloc-unsafe: 1.1.0 - buffer-fill: 1.0.0 - - buffer-fill@1.0.0: {} - - buffer-v6-polyfill@1.0.5: {} - - buffer@5.7.1: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - - call-once-fn@1.0.15: {} - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - chalk@5.4.1: {} - - chownr@1.1.4: {} - - cli-cursor@5.0.0: - dependencies: - restore-cursor: 5.1.0 - - cli-progress@3.12.0: - dependencies: - string-width: 4.2.3 - - cli-truncate@4.0.0: - dependencies: - slice-ansi: 5.0.0 - string-width: 7.2.0 - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - color-string@1.9.1: - dependencies: - color-name: 1.1.4 - simple-swizzle: 0.2.2 - - color@4.2.3: - dependencies: - color-convert: 2.0.1 - color-string: 1.9.1 - - colorette@2.0.20: {} - - commander@12.1.0: {} - - commander@6.2.1: {} - - commander@9.5.0: {} - - concat-map@0.0.1: - optional: true - - content-disposition@0.5.4: - dependencies: - safe-buffer: 5.2.1 - - core-js-pure@3.40.0: {} - - core-util-is@1.0.3: {} - - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - debug@4.4.0: - dependencies: - ms: 2.1.3 - - decompress-response@6.0.0: - dependencies: - mimic-response: 3.1.0 - - deep-extend@0.6.0: {} - - detect-libc@2.0.3: {} - - duplexify@4.1.3: - dependencies: - end-of-stream: 1.4.4 - inherits: 2.0.4 - readable-stream: 3.6.2 - stream-shift: 1.0.3 - - emoji-regex@10.4.0: {} - - emoji-regex@8.0.0: {} - - end-of-stream@1.4.4: - dependencies: - once: 1.4.0 - - environment@1.1.0: {} - - esprima@4.0.1: {} - - eventemitter3@5.0.1: {} - - execa@5.1.1: - dependencies: - cross-spawn: 7.0.6 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - - execa@8.0.1: - dependencies: - cross-spawn: 7.0.6 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 - - expand-template@2.0.3: {} - - extract-base-iterator@1.2.22(glob@7.2.3): - dependencies: - graceful-fs: 4.2.11 - is-absolute: 1.0.0 - lodash.compact: 3.0.1 - mkdirp-classic: 0.5.3 - object-assign: 4.1.1 - queue-cb: 1.4.16 - rimraf2: 2.8.2(glob@7.2.3) - stack-base-iterator: 1.1.20 - transitivePeerDependencies: - - glob - - fast-extract@1.3.31(glob@7.2.3): - dependencies: - bl: 3.0.1 - buffer-v6-polyfill: 1.0.5 - call-once-fn: 1.0.15 - content-disposition: 0.5.4 - flush-write-stream: 2.0.0 - lodash.throttle: 4.1.1 - mkdirp-classic: 0.5.3 - mock-require-lazy: 1.0.14 - next-tick: 1.1.0 - on-one: 0.1.4 - progress-stream: 2.0.0 - pumpify: 2.0.1 - queue-cb: 1.4.16 - readable-stream: 2.3.8 - require_optional: 1.0.1 - rimraf2: 2.8.2(glob@7.2.3) - signal-exit: 3.0.7 - tar-iterator: 1.2.25(glob@7.2.3) - temp-suffix: 0.1.14 - unbzip2-stream: 1.4.3 - zip-iterator: 1.2.23(glob@7.2.3) - transitivePeerDependencies: - - glob - - fifo@2.4.1: {} - - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - - flush-write-stream@2.0.0: - dependencies: - inherits: 2.0.4 - readable-stream: 3.6.2 - - follow-redirects@1.15.9: {} - - fs-constants@1.0.0: {} - - fs-extra@10.1.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - - fs.realpath@1.0.0: - optional: true - - get-caller-file@2.0.5: {} - - get-east-asian-width@1.3.0: {} - - get-stream@6.0.1: {} - - get-stream@8.0.1: {} - - github-from-package@0.0.0: {} - - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - optional: true - - globalyzer@0.1.0: {} - - globrex@0.1.2: {} - - graceful-fs@4.2.11: {} - - has-flag@4.0.0: {} - - hash-string@1.0.0: {} - - human-signals@2.1.0: {} - - human-signals@5.0.0: {} - - husky@9.1.7: {} - - ieee754@1.2.1: {} - - imurmurhash@0.1.4: {} - - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - optional: true - - inherits@2.0.4: {} - - ini@1.3.8: {} - - ini@3.0.1: {} - - is-absolute@1.0.0: - dependencies: - is-relative: 1.0.0 - is-windows: 1.0.2 - - is-apple-silicon@https://codeload.github.com/trickypr/is-apple-silicon/tar.gz/5f75501a1d7566ba9f94174b6825d7bd9d302b6a: {} - - is-arrayish@0.3.2: {} - - is-error@2.2.2: {} - - is-fullwidth-code-point@3.0.0: {} - - is-fullwidth-code-point@4.0.0: {} - - is-fullwidth-code-point@5.0.0: - dependencies: - get-east-asian-width: 1.3.0 - - is-number@7.0.0: {} - - is-promise@4.0.0: {} - - is-relative@1.0.0: - dependencies: - is-unc-path: 1.0.0 - - is-stream@2.0.1: {} - - is-stream@3.0.0: {} - - is-unc-path@1.0.0: - dependencies: - unc-path-regex: 0.1.2 - - is-windows@1.0.2: {} - - isarray@1.0.0: {} - - isexe@2.0.0: {} - - js-yaml@3.14.1: - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - - jsonfile@6.1.0: - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - - kleur@3.0.3: {} - - kleur@4.1.5: {} - - lifecycle@1.0.4: {} - - lilconfig@3.1.3: {} - - lint-staged@15.3.0: - dependencies: - chalk: 5.4.1 - commander: 12.1.0 - debug: 4.4.0 - execa: 8.0.1 - lilconfig: 3.1.3 - listr2: 8.2.5 - micromatch: 4.0.8 - pidtree: 0.6.0 - string-argv: 0.3.2 - yaml: 2.6.1 - transitivePeerDependencies: - - supports-color - - listr2@8.2.5: - dependencies: - cli-truncate: 4.0.0 - colorette: 2.0.20 - eventemitter3: 5.0.1 - log-update: 6.1.0 - rfdc: 1.4.1 - wrap-ansi: 9.0.0 - - lodash.compact@3.0.1: {} - - lodash.throttle@4.1.1: {} - - log-update@6.1.0: - dependencies: - ansi-escapes: 7.0.0 - cli-cursor: 5.0.0 - slice-ansi: 7.1.0 - strip-ansi: 7.1.0 - wrap-ansi: 9.0.0 - - merge-stream@2.0.0: {} - - micromatch@4.0.8: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - - mimic-fn@2.1.0: {} - - mimic-fn@4.0.0: {} - - mimic-function@5.0.1: {} - - mimic-response@3.1.0: {} - - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.11 - optional: true - - minimist@1.2.8: {} - - mkdirp-classic@0.5.3: {} - - mock-require-lazy@1.0.14: - dependencies: - get-caller-file: 2.0.5 - normalize-path: 3.0.0 - - modern-async@1.1.5: - dependencies: - core-js-pure: 3.40.0 - nanoassert: 2.0.0 - - mount-dmg@1.0.1: - dependencies: - shell-escape: 0.2.0 - - ms@2.1.3: {} - - mvdan-sh@0.10.1: {} - - nanoassert@2.0.0: {} - - napi-build-utils@2.0.0: {} - - next-tick@1.1.0: {} - - node-abi@3.73.0: - dependencies: - semver: 7.6.3 - - node-addon-api@5.1.0: {} - - normalize-path@3.0.0: {} - - npm-run-path@4.0.1: - dependencies: - path-key: 3.1.1 - - npm-run-path@5.3.0: - dependencies: - path-key: 4.0.0 - - object-assign@4.1.1: {} - - on-one@0.1.4: {} - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - onetime@5.1.2: - dependencies: - mimic-fn: 2.1.0 - - onetime@6.0.0: - dependencies: - mimic-fn: 4.0.0 - - onetime@7.0.0: - dependencies: - mimic-function: 5.0.1 - - os-shim@0.1.3: {} - - path-is-absolute@1.0.1: - optional: true - - path-key@3.1.1: {} - - path-key@4.0.0: {} - - picomatch@2.3.1: {} - - pidtree@0.6.0: {} - - png-to-ico@2.1.8: - dependencies: - '@types/node': 17.0.45 - minimist: 1.2.8 - pngjs: 6.0.0 - - pngjs@6.0.0: {} - - prebuild-install@7.1.3: - dependencies: - detect-libc: 2.0.3 - expand-template: 2.0.3 - github-from-package: 0.0.0 - minimist: 1.2.8 - mkdirp-classic: 0.5.3 - napi-build-utils: 2.0.0 - node-abi: 3.73.0 - pump: 3.0.2 - rc: 1.2.8 - simple-get: 4.0.1 - tar-fs: 2.1.2 - tunnel-agent: 0.6.0 - - prettier-plugin-sh@0.14.0(prettier@3.4.2): - dependencies: - mvdan-sh: 0.10.1 - prettier: 3.4.2 - sh-syntax: 0.4.2 - - prettier@3.4.2: {} - - process-nextick-args@2.0.1: {} - - progress-stream@2.0.0: - dependencies: - speedometer: 1.0.0 - through2: 2.0.5 - - prompts@2.4.2: - dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 - - pump@3.0.2: - dependencies: - end-of-stream: 1.4.4 - once: 1.4.0 - - pumpify@2.0.1: - dependencies: - duplexify: 4.1.3 - inherits: 2.0.4 - pump: 3.0.2 - - queue-cb@1.4.16: {} - - rc@1.2.8: - dependencies: - deep-extend: 0.6.0 - ini: 1.3.8 - minimist: 1.2.8 - strip-json-comments: 2.0.1 - - readable-stream@2.3.8: - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - - readable-stream@3.6.2: - dependencies: - inherits: 2.0.4 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - - require_optional@1.0.1: - dependencies: - resolve-from: 2.0.0 - semver: 5.7.2 - - resolve-from@2.0.0: {} - - restore-cursor@5.1.0: - dependencies: - onetime: 7.0.0 - signal-exit: 4.1.0 - - rfdc@1.4.1: {} - - rimraf2@2.8.2(glob@7.2.3): - optionalDependencies: - glob: 7.2.3 - - rustic@1.2.2: {} - - safe-buffer@5.1.2: {} - - safe-buffer@5.2.1: {} - - semver@5.7.2: {} - - semver@7.6.3: {} - - sh-syntax@0.4.2: - dependencies: - tslib: 2.8.1 - - sharp@0.30.7: - dependencies: - color: 4.2.3 - detect-libc: 2.0.3 - node-addon-api: 5.1.0 - prebuild-install: 7.1.3 - semver: 7.6.3 - simple-get: 4.0.1 - tar-fs: 2.1.2 - tunnel-agent: 0.6.0 - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - shell-escape@0.2.0: {} - - short-hash@1.0.0: - dependencies: - hash-string: 1.0.0 - - signal-exit@3.0.7: {} - - signal-exit@4.1.0: {} - - simple-concat@1.0.1: {} - - simple-get@4.0.1: - dependencies: - decompress-response: 6.0.0 - once: 1.4.0 - simple-concat: 1.0.1 - - simple-swizzle@0.2.2: - dependencies: - is-arrayish: 0.3.2 - - sisteransi@1.0.5: {} - - slice-ansi@5.0.0: - dependencies: - ansi-styles: 6.2.1 - is-fullwidth-code-point: 4.0.0 - - slice-ansi@7.1.0: - dependencies: - ansi-styles: 6.2.1 - is-fullwidth-code-point: 5.0.0 - - speedometer@1.0.0: {} - - sprintf-js@1.0.3: {} - - stack-base-iterator@1.1.20: - dependencies: - asap: 2.0.6 - async-compat: 1.6.8 - call-once-fn: 1.0.15 - fifo: 2.4.1 - - stream-shift@1.0.3: {} - - string-argv@0.3.2: {} - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - string-width@7.2.0: - dependencies: - emoji-regex: 10.4.0 - get-east-asian-width: 1.3.0 - strip-ansi: 7.1.0 - - string_decoder@1.1.1: - dependencies: - safe-buffer: 5.1.2 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-ansi@7.1.0: - dependencies: - ansi-regex: 6.1.0 - - strip-final-newline@2.0.0: {} - - strip-final-newline@3.0.0: {} - - strip-json-comments@2.0.1: {} - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - tar-fs@2.1.2: - dependencies: - chownr: 1.1.4 - mkdirp-classic: 0.5.3 - pump: 3.0.2 - tar-stream: 2.2.0 - - tar-iterator@1.2.25(glob@7.2.3): - dependencies: - call-once-fn: 1.0.15 - extract-base-iterator: 1.2.22(glob@7.2.3) - lifecycle: 1.0.4 - lodash.compact: 3.0.1 - mkdirp-classic: 0.5.3 - on-one: 0.1.4 - rimraf2: 2.8.2(glob@7.2.3) - tar-stream-compat: 2.1.5 - transitivePeerDependencies: - - glob - - tar-stream-compat@2.1.5: - dependencies: - bl: 2.2.1 - buffer-alloc: 1.2.0 - end-of-stream: 1.4.4 - fs-constants: 1.0.0 - inherits: 2.0.4 - readable-stream: 2.3.8 - - tar-stream@2.2.0: - dependencies: - bl: 4.1.0 - end-of-stream: 1.4.4 - fs-constants: 1.0.0 - inherits: 2.0.4 - readable-stream: 3.6.2 - - temp-suffix@0.1.14: - dependencies: - imurmurhash: 0.1.4 - - through2@2.0.5: - dependencies: - readable-stream: 2.3.8 - xtend: 4.0.2 - - through@2.3.8: {} - - tiny-glob@0.2.9: - dependencies: - globalyzer: 0.1.0 - globrex: 0.1.2 - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - to-utf8@0.0.1: {} - - tslib@2.8.1: {} - - tunnel-agent@0.6.0: - dependencies: - safe-buffer: 5.2.1 - - unbzip2-stream@1.4.3: - dependencies: - buffer: 5.7.1 - through: 2.3.8 - - unc-path-regex@0.1.2: {} - - universalify@2.0.1: {} - - util-deprecate@1.0.2: {} - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - wrap-ansi@9.0.0: - dependencies: - ansi-styles: 6.2.1 - string-width: 7.2.0 - strip-ansi: 7.1.0 - - wrappy@1.0.2: {} - - xmlbuilder2@3.1.1: - dependencies: - '@oozcitak/dom': 1.15.10 - '@oozcitak/infra': 1.0.8 - '@oozcitak/util': 8.3.8 - js-yaml: 3.14.1 - - xtend@4.0.2: {} - - yaml@2.6.1: {} - - zip-iterator@1.2.23(glob@7.2.3): - dependencies: - buffer-v6-polyfill: 1.0.5 - call-once-fn: 1.0.15 - extract-base-iterator: 1.2.22(glob@7.2.3) - lifecycle: 1.0.4 - lodash.compact: 3.0.1 - mkdirp-classic: 0.5.3 - on-one: 0.1.4 - os-shim: 0.1.3 - queue-cb: 1.4.16 - readable-stream: 2.3.8 - rimraf2: 2.8.2(glob@7.2.3) - short-hash: 1.0.0 - temp-suffix: 0.1.14 - zip: 1.2.0 - transitivePeerDependencies: - - glob - - zip@1.2.0: - dependencies: - bops: 0.1.1 From 07afc4810a9a9b20c5ae6f2ff510be9cb22c957e Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sat, 8 Mar 2025 11:51:50 +0100 Subject: [PATCH 071/127] Adjust URL bar height and update layout handling for compact mode --- src/browser/base/content/ZenUIManager.mjs | 6 ++++++ .../themes/shared/urlbar-searchbar-css.patch | 13 +------------ 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/browser/base/content/ZenUIManager.mjs b/src/browser/base/content/ZenUIManager.mjs index 9673974a0..b8d3a3460 100644 --- a/src/browser/base/content/ZenUIManager.mjs +++ b/src/browser/base/content/ZenUIManager.mjs @@ -620,6 +620,12 @@ var gZenVerticalTabsManager = { } gZenCompactModeManager.updateCompactModeContext(isSingleToolbar); + document.getElementById("urlbar").removeAttribute('--urlbar-height'); + if (!isSingleToolbar) { + document.getElementById("urlbar").style.setProperty('--urlbar-height', '32px'); + } else { + gURLBar.updateLayoutBreakout(); + } // Always move the splitter next to the sidebar this.navigatorToolbox.after(document.getElementById('zen-sidebar-splitter')); diff --git a/src/browser/themes/shared/urlbar-searchbar-css.patch b/src/browser/themes/shared/urlbar-searchbar-css.patch index b41a61211..259fe7eaf 100644 --- a/src/browser/themes/shared/urlbar-searchbar-css.patch +++ b/src/browser/themes/shared/urlbar-searchbar-css.patch @@ -1,5 +1,5 @@ diff --git a/browser/themes/shared/urlbar-searchbar.css b/browser/themes/shared/urlbar-searchbar.css -index 574f83af7fa49ddcdff6711ca8b1d3bed1a35e0c..7919f21f6b0b4df2f197b9c6f0e134ff85d50d0a 100644 +index 574f83af7fa49ddcdff6711ca8b1d3bed1a35e0c..c2e8cb8b37438176db07a47e1e975ae1aea42252 100644 --- a/browser/themes/shared/urlbar-searchbar.css +++ b/browser/themes/shared/urlbar-searchbar.css @@ -5,7 +5,7 @@ @@ -22,14 +22,3 @@ index 574f83af7fa49ddcdff6711ca8b1d3bed1a35e0c..7919f21f6b0b4df2f197b9c6f0e134ff width: calc(var(--urlbar-width) + 2 * var(--urlbar-margin-inline)); > .urlbar-input-container { -@@ -583,8 +585,8 @@ - .urlbar-revert-button, - .urlbar-go-button, - .search-go-button { -- width: calc(var(--urlbar-min-height) - 2px /* border */ - 2 * var(--urlbar-container-padding)); -- height: calc(var(--urlbar-min-height) - 2px /* border */ - 2 * var(--urlbar-container-padding)); -+ width: calc(var(--urlbar-min-height) + 2px /* border */ - 2 * var(--urlbar-container-padding)); -+ height: calc(var(--urlbar-min-height) + 2px /* border */ - 2 * var(--urlbar-container-padding)); - border-radius: var(--urlbar-icon-border-radius); - padding: var(--urlbar-icon-padding); - color: inherit; From 7b029cc7bcc17018fe9c79dd9f655717ff5affaf Mon Sep 17 00:00:00 2001 From: noaione Date: Sat, 8 Mar 2025 19:53:48 +0700 Subject: [PATCH 072/127] Pass new tab URL to Zen `selectEmptyTab` This will ensure private browsing mode to not open the standard new tab. --- src/browser/base/content/ZenUIManager.mjs | 4 ++-- src/browser/base/zen-components/ZenWorkspaces.mjs | 5 +++-- .../components/tabbrowser/content/tabbrowser-js.patch | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/browser/base/content/ZenUIManager.mjs b/src/browser/base/content/ZenUIManager.mjs index b8d3a3460..7b2cff504 100644 --- a/src/browser/base/content/ZenUIManager.mjs +++ b/src/browser/base/content/ZenUIManager.mjs @@ -620,9 +620,9 @@ var gZenVerticalTabsManager = { } gZenCompactModeManager.updateCompactModeContext(isSingleToolbar); - document.getElementById("urlbar").removeAttribute('--urlbar-height'); + document.getElementById('urlbar').removeAttribute('--urlbar-height'); if (!isSingleToolbar) { - document.getElementById("urlbar").style.setProperty('--urlbar-height', '32px'); + document.getElementById('urlbar').style.setProperty('--urlbar-height', '32px'); } else { gURLBar.updateLayoutBreakout(); } diff --git a/src/browser/base/zen-components/ZenWorkspaces.mjs b/src/browser/base/zen-components/ZenWorkspaces.mjs index 53f911a36..f4667a18b 100644 --- a/src/browser/base/zen-components/ZenWorkspaces.mjs +++ b/src/browser/base/zen-components/ZenWorkspaces.mjs @@ -111,12 +111,13 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { ); } - selectEmptyTab() { + selectEmptyTab(newTabTarget = null) { if (this._emptyTab && gZenVerticalTabsManager._canReplaceNewTab) { gBrowser.selectedTab = this._emptyTab; return this._emptyTab; } - let tab = gZenUIManager.openAndChangeToTab(Services.prefs.getStringPref('browser.startup.homepage')); + const newTabUrl = newTabTarget || Services.prefs.getStringPref('browser.startup.homepage'); + let tab = gZenUIManager.openAndChangeToTab(newTabUrl); if (window.uuid) { tab.setAttribute('zen-workspace-id', this.activeWorkspace); } diff --git a/src/browser/components/tabbrowser/content/tabbrowser-js.patch b/src/browser/components/tabbrowser/content/tabbrowser-js.patch index 261f98a20..da59666c3 100644 --- a/src/browser/components/tabbrowser/content/tabbrowser-js.patch +++ b/src/browser/components/tabbrowser/content/tabbrowser-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js -index 628aa6596627c85efe361fc1ece8fd58f7ee653e..c62727bad57eda3b9d9a73c1df739a92f194f0c2 100644 +index 628aa6596627c85efe361fc1ece8fd58f7ee653e..6bd5149f4be6c18cbf733b5b9ee01534af61bef9 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js @@ -412,11 +412,50 @@ @@ -476,7 +476,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..c62727bad57eda3b9d9a73c1df739a92 - this.addTrustedTab(BROWSER_NEW_TAB_URL, { - skipAnimation: true, - }); -+ ZenWorkspaces.selectEmptyTab(); ++ ZenWorkspaces.selectEmptyTab(BROWSER_NEW_TAB_URL); } else { TabBarVisibility.update(); } From a93fdf5a1771abedee9a793112349be1f2adaf53 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sat, 8 Mar 2025 18:51:46 +0100 Subject: [PATCH 073/127] Refactor URL bar height handling and improve drag-and-drop tab functionality in ZenViewSplitter --- src/browser/base/content/ZenUIManager.mjs | 4 +- .../base/zen-components/ZenViewSplitter.mjs | 10 ++- .../tabbrowser/content/tabs-js.patch | 74 ++++++++++--------- 3 files changed, 48 insertions(+), 40 deletions(-) diff --git a/src/browser/base/content/ZenUIManager.mjs b/src/browser/base/content/ZenUIManager.mjs index b8d3a3460..7b2cff504 100644 --- a/src/browser/base/content/ZenUIManager.mjs +++ b/src/browser/base/content/ZenUIManager.mjs @@ -620,9 +620,9 @@ var gZenVerticalTabsManager = { } gZenCompactModeManager.updateCompactModeContext(isSingleToolbar); - document.getElementById("urlbar").removeAttribute('--urlbar-height'); + document.getElementById('urlbar').removeAttribute('--urlbar-height'); if (!isSingleToolbar) { - document.getElementById("urlbar").style.setProperty('--urlbar-height', '32px'); + document.getElementById('urlbar').style.setProperty('--urlbar-height', '32px'); } else { gURLBar.updateLayoutBreakout(); } diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index 200976181..07cb872cf 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -305,7 +305,8 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { } this.fakeBrowser.classList.add('fade-out'); const side = this.fakeBrowser.getAttribute('side'); - gBrowser.selectedTab = this._draggingTab; + if (this._draggingTab) this._draggingTab.setAttribute('zen-has-splitted', 'true'); + this._lastOpenedTab = gBrowser.selectedTab; this._draggingTab = null; try { Promise.all([ @@ -1522,7 +1523,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { delete this._hasAnimated; this.fakeBrowser.remove(); this.fakeBrowser = null; - this._draggingTab._visuallySelected = false; + if (this._draggingTab) this._draggingTab._visuallySelected = false; if (select) { gBrowser.selectedTab = this._draggingTab; this._draggingTab = null; @@ -1548,7 +1549,10 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { const dropSide = this.fakeBrowser?.getAttribute('side'); const containerRect = this.fakeBrowser.getBoundingClientRect(); const padding = Services.prefs.getIntPref('zen.theme.content-element-separation', 0); - const dropTarget = document.elementFromPoint(containerRect.left + containerRect.width + padding + 5, event.clientY); + const dropTarget = document.elementFromPoint( + side == 'left' ? containerRect.left + containerRect.width + padding + 5 : containerRect.left - padding - 5, + event.clientY + ); const browser = dropTarget?.closest('browser'); if (!browser) { diff --git a/src/browser/components/tabbrowser/content/tabs-js.patch b/src/browser/components/tabbrowser/content/tabs-js.patch index 7185fe630..e1507c084 100644 --- a/src/browser/components/tabbrowser/content/tabs-js.patch +++ b/src/browser/components/tabbrowser/content/tabs-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js -index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620036896db 100644 +index fa96568d366fd3608f9bd583fa793150bd815c8b..24071f1bc0d9cb2a4fe66e5e4657a64ab66f29cf 100644 --- a/browser/components/tabbrowser/content/tabs.js +++ b/browser/components/tabbrowser/content/tabs.js @@ -94,7 +94,7 @@ @@ -56,10 +56,14 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 if ( (effects == "move" || effects == "copy") && this == draggedTab.container && -@@ -996,6 +1002,14 @@ +@@ -996,6 +1002,18 @@ this._tabDropIndicator.hidden = true; event.stopPropagation(); ++ if (draggedTab.hasAttribute("zen-has-splitted")) { ++ draggedTab.removeAttribute("zen-has-splitted"); ++ draggedTab._visuallySelected = false; ++ } + if (draggedTab && dropEffect == "move") { + let moved = gZenPinnedTabManager.moveToAnotherTabContainerIfNecessary(event, movingTabs); + @@ -71,7 +75,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 if (draggedTab && dropEffect == "copy") { // copy the dropped tab (wherever it's from) let newIndex = this._getDropIndex(event); -@@ -1034,10 +1048,11 @@ +@@ -1034,10 +1052,11 @@ } } else { let pinned = draggedTab.pinned; @@ -87,7 +91,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 ); let size = this.verticalMode ? "height" : "width"; let screenAxis = this.verticalMode ? "screenY" : "screenX"; -@@ -1114,7 +1129,7 @@ +@@ -1114,7 +1133,7 @@ let postTransitionCleanup = () => { tab.removeAttribute("tabdrop-samewindow"); @@ -96,7 +100,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 if (dropIndex !== false) { gBrowser.moveTabTo(tab, dropIndex); if (!directionForward) { -@@ -1122,7 +1137,7 @@ +@@ -1122,7 +1141,7 @@ } } }; @@ -105,7 +109,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 postTransitionCleanup(); } else { let onTransitionEnd = transitionendEvent => { -@@ -1249,7 +1264,7 @@ +@@ -1249,7 +1268,7 @@ return; } } @@ -114,7 +118,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 gBrowser.loadTabs(urls, { inBackground, replace, -@@ -1279,13 +1294,23 @@ +@@ -1279,13 +1298,23 @@ return; } @@ -140,7 +144,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 ) { delete draggedTab._dragData; return; -@@ -1517,7 +1542,7 @@ +@@ -1517,7 +1546,7 @@ } get newTabButton() { @@ -149,7 +153,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 } get verticalMode() { -@@ -1537,28 +1562,40 @@ +@@ -1537,28 +1566,40 @@ if (this.#allTabs) { return this.#allTabs; } @@ -198,7 +202,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 return children.filter(node => node.tagName == "tab-group"); } -@@ -1579,7 +1616,7 @@ +@@ -1579,7 +1620,7 @@ */ get visibleTabs() { if (!this.#visibleTabs) { @@ -207,7 +211,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 } return this.#visibleTabs; } -@@ -1613,10 +1650,8 @@ +@@ -1613,10 +1654,8 @@ return this.#focusableItems; } @@ -220,7 +224,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 let focusableItems = []; for (let child of children) { -@@ -1632,6 +1667,7 @@ +@@ -1632,6 +1671,7 @@ } this.#focusableItems = [ @@ -228,7 +232,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 ...verticalPinnedTabsContainer.children, ...focusableItems, ]; -@@ -1642,6 +1678,7 @@ +@@ -1642,6 +1682,7 @@ _invalidateCachedTabs() { this.#allTabs = null; this._invalidateCachedVisibleTabs(); @@ -236,7 +240,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 } _invalidateCachedVisibleTabs() { -@@ -1656,8 +1693,8 @@ +@@ -1656,8 +1697,8 @@ #isContainerVerticalPinnedExpanded(tab) { return ( this.verticalMode && @@ -247,7 +251,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 ); } -@@ -1672,7 +1709,7 @@ +@@ -1672,7 +1713,7 @@ if (node == null) { // We have a container for non-tab elements at the end of the scrollbox. @@ -256,7 +260,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 } node.before(tab); -@@ -1772,7 +1809,7 @@ +@@ -1772,7 +1813,7 @@ // There are separate "new tab" buttons for horizontal tabs toolbar, vertical tabs and // for when the tab strip is overflowed (which is shared by vertical and horizontal tabs); // Attach the long click popup to all of them. @@ -265,7 +269,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 const newTab2 = this.newTabButton; const newTabVertical = document.getElementById( "vertical-tabs-newtab-button" -@@ -1855,7 +1892,7 @@ +@@ -1855,7 +1896,7 @@ let rect = ele => { return window.windowUtils.getBoundsWithoutFlushing(ele); }; @@ -274,7 +278,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 if (tab && rect(tab).width <= this._tabClipWidth) { this.setAttribute("closebuttons", "activetab"); } else { -@@ -1867,10 +1904,12 @@ +@@ -1867,10 +1908,12 @@ _handleTabSelect(aInstant) { let selectedTab = this.selectedItem; @@ -287,7 +291,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 selectedTab._notselectedsinceload = false; } -@@ -1882,7 +1921,7 @@ +@@ -1882,7 +1925,7 @@ return; } @@ -296,7 +300,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 if (!tabs.length) { return; } -@@ -1918,7 +1957,7 @@ +@@ -1918,7 +1961,7 @@ if (isEndTab && !this._hasTabTempMaxWidth) { return; } @@ -305,7 +309,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 // Force tabs to stay the same width, unless we're closing the last tab, // which case we need to let them expand just enough so that the overall // tabbar width is the same. -@@ -1933,7 +1972,7 @@ +@@ -1933,7 +1976,7 @@ let tabsToReset = []; for (let i = numPinned; i < tabs.length; i++) { let tab = tabs[i]; @@ -314,7 +318,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 if (!isEndTab) { // keep tabs the same width tab.style.transition = "none"; -@@ -1999,16 +2038,15 @@ +@@ -1999,16 +2042,15 @@ // Move pinned tabs to another container when the tabstrip is toggled to vertical // and when session restore code calls _positionPinnedTabs; update styling whenever // the number of pinned tabs changes. @@ -337,7 +341,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 } } -@@ -2016,9 +2054,7 @@ +@@ -2016,9 +2058,7 @@ } _resetVerticalPinnedTabs() { @@ -348,7 +352,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 if (!verticalTabsContainer.children.length) { return; -@@ -2031,8 +2067,8 @@ +@@ -2031,8 +2071,8 @@ } _positionPinnedTabs() { @@ -359,7 +363,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 let absPositionHorizontalTabs = this.overflowing && tabs.length > numPinned && numPinned > 0; -@@ -2041,7 +2077,7 @@ +@@ -2041,7 +2081,7 @@ if (this.verticalMode) { this._updateVerticalPinnedTabs(); @@ -368,7 +372,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 let layoutData = this._pinnedTabsLayoutCache; let uiDensity = document.documentElement.getAttribute("uidensity"); if (!layoutData || layoutData.uiDensity != uiDensity) { -@@ -2113,7 +2149,7 @@ +@@ -2113,7 +2153,7 @@ return; } @@ -377,7 +381,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 let directionX = screenX > dragData.animLastScreenX; let directionY = screenY > dragData.animLastScreenY; -@@ -2121,7 +2157,7 @@ +@@ -2121,7 +2161,7 @@ dragData.animLastScreenX = screenX; let { width: tabWidth, height: tabHeight } = @@ -386,7 +390,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 let shiftSizeX = tabWidth * movingTabs.length; let shiftSizeY = tabHeight; dragData.tabWidth = tabWidth; -@@ -2296,10 +2332,11 @@ +@@ -2296,10 +2336,11 @@ } let pinned = draggedTab.pinned; @@ -402,7 +406,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 ); if (this.#rtlMode) { -@@ -2348,7 +2385,11 @@ +@@ -2348,7 +2389,11 @@ translate = Math.min(Math.max(translate, firstBound), lastBound); for (let tab of movingTabs) { @@ -415,7 +419,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 } dragData.translatePos = translate; -@@ -2484,12 +2525,16 @@ +@@ -2484,12 +2529,16 @@ // Shift background tabs to leave a gap where the dragged tab // would currently be dropped. for (let tab of tabs) { @@ -433,7 +437,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 if (tab.group?.tabs[0] == tab) { tab.group.style.setProperty( "--tabgroup-dragover-transform", -@@ -2541,8 +2586,9 @@ +@@ -2541,8 +2590,9 @@ ); } @@ -445,7 +449,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 return; } -@@ -2553,6 +2599,7 @@ +@@ -2553,6 +2603,7 @@ tab.style.transform = ""; if (tab.group) { tab.group.style.removeProperty("--tabgroup-dragover-transform"); @@ -453,7 +457,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 } tab.removeAttribute("dragover-createGroup"); } -@@ -2604,7 +2651,7 @@ +@@ -2604,7 +2655,7 @@ movingTab._moveTogetherSelectedTabsData.newIndex = movingTabNewIndex; movingTab._moveTogetherSelectedTabsData.animate = false; }; @@ -462,7 +466,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 postTransitionCleanup(); } else { let onTransitionEnd = transitionendEvent => { -@@ -2707,9 +2754,9 @@ +@@ -2707,9 +2758,9 @@ function newIndex(aTab, index) { // Don't allow mixing pinned and unpinned tabs. if (aTab.pinned) { @@ -474,7 +478,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..64e93a414f1544b89af05c636c587620 } } -@@ -2793,7 +2840,7 @@ +@@ -2793,7 +2844,7 @@ } _notifyBackgroundTab(aTab) { From 6d164511b4ad3dbedc6d292c63de16c59054bd91 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sat, 8 Mar 2025 19:43:12 +0100 Subject: [PATCH 074/127] Add error handling to tab animation and refine empty tab selection logic --- src/browser/base/content/ZenUIManager.mjs | 58 ++++++++++--------- .../base/zen-components/ZenWorkspaces.mjs | 2 +- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/src/browser/base/content/ZenUIManager.mjs b/src/browser/base/content/ZenUIManager.mjs index 7b2cff504..f644915ca 100644 --- a/src/browser/base/content/ZenUIManager.mjs +++ b/src/browser/base/content/ZenUIManager.mjs @@ -347,33 +347,37 @@ var gZenVerticalTabsManager = { return visibleTabs[visibleTabs.length - 1] === aTab; }; - const tabSize = aTab.getBoundingClientRect().height; - const transform = `-${tabSize}px`; - gZenUIManager.motion - .animate( - aTab, - { - opacity: [0, 1], - transform: ['scale(0.95)', 'scale(1)'], - marginBottom: isLastTab() ? [] : [transform, '0px'], - }, - { - duration: 0.2, - easing: 'ease-out', - } - ) - .then(() => { - aTab.style.removeProperty('margin-bottom'); - aTab.style.removeProperty('transform'); - aTab.style.removeProperty('opacity'); - }); - gZenUIManager.motion - .animate(aTab.querySelector('.tab-content'), { - filter: ['blur(1px)', 'blur(0px)'], - }) - .then(() => { - aTab.querySelector('.tab-stack').style.removeProperty('filter'); - }); + try { + const tabSize = aTab.getBoundingClientRect().height; + const transform = `-${tabSize}px`; + gZenUIManager.motion + .animate( + aTab, + { + opacity: [0, 1], + transform: ['scale(0.95)', 'scale(1)'], + marginBottom: isLastTab() ? [] : [transform, '0px'], + }, + { + duration: 0.2, + easing: 'ease-out', + } + ) + .then(() => { + aTab.style.removeProperty('margin-bottom'); + aTab.style.removeProperty('transform'); + aTab.style.removeProperty('opacity'); + }); + gZenUIManager.motion + .animate(aTab.querySelector('.tab-content'), { + filter: ['blur(1px)', 'blur(0px)'], + }) + .then(() => { + aTab.querySelector('.tab-stack').style.removeProperty('filter'); + }); + } catch (e) { + console.error(e); + } }, get actualWindowButtons() { diff --git a/src/browser/base/zen-components/ZenWorkspaces.mjs b/src/browser/base/zen-components/ZenWorkspaces.mjs index f4667a18b..bf9b09240 100644 --- a/src/browser/base/zen-components/ZenWorkspaces.mjs +++ b/src/browser/base/zen-components/ZenWorkspaces.mjs @@ -628,7 +628,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { (currentTab.isEmpty && (currentTab.getAttribute('image') === gPageIcons[currentTabURL] || !currentTab.hasAttribute('image'))) || currentTab.hasAttribute('zen-empty-tab') || - currentTab._possibleEmptyTab + (currentTab._possibleEmptyTab && currentTab.isEmpty) ) { this.selectEmptyTab(); this._removedByStartupPage = true; From cf807ea93ec9880f82108f360d1e155897e3f2f7 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sat, 8 Mar 2025 19:45:39 +0100 Subject: [PATCH 075/127] Format export statement for consistency in AppRun script --- AppDir/AppRun | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppDir/AppRun b/AppDir/AppRun index 5a6c5706d..105e0801a 100644 --- a/AppDir/AppRun +++ b/AppDir/AppRun @@ -1,6 +1,6 @@ #!/bin/sh CURRENTDIR="$(dirname "$(readlink -f "$0")")" export PATH="${CURRENTDIR}:${PATH}" -export MOZ_LEGACY_PROFILES=1 # Prevent per installation profiles +export MOZ_LEGACY_PROFILES=1 # Prevent per installation profiles export MOZ_APP_LAUNCHER="${APPIMAGE}" # Allows setting as default browser exec "${CURRENTDIR}/zen" "$@" From 163d2c8d8f6e456512e81bce2ba701425b545ef1 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sat, 8 Mar 2025 23:59:38 +0100 Subject: [PATCH 076/127] Add workspace selector to bookmark edit panel and ensure ZenWorkspaces is defined --- .../base/zen-components/ZenWorkspacesStorage.mjs | 1 + .../places/content/editBookmarkPanel-inc-xhtml.patch | 12 +++++------- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/browser/base/zen-components/ZenWorkspacesStorage.mjs b/src/browser/base/zen-components/ZenWorkspacesStorage.mjs index 261842779..f2bf4f628 100644 --- a/src/browser/base/zen-components/ZenWorkspacesStorage.mjs +++ b/src/browser/base/zen-components/ZenWorkspacesStorage.mjs @@ -7,6 +7,7 @@ var ZenWorkspacesStorage = { Weave: 'resource://services-sync/main.sys.mjs', }); + if (!window.ZenWorkspaces) return; await this._ensureTable(); await ZenWorkspaceBookmarksStorage.init(); }, diff --git a/src/browser/components/places/content/editBookmarkPanel-inc-xhtml.patch b/src/browser/components/places/content/editBookmarkPanel-inc-xhtml.patch index 87cd3f11f..11cd754f0 100644 --- a/src/browser/components/places/content/editBookmarkPanel-inc-xhtml.patch +++ b/src/browser/components/places/content/editBookmarkPanel-inc-xhtml.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/places/content/editBookmarkPanel.inc.xhtml b/browser/components/places/content/editBookmarkPanel.inc.xhtml -index 40366677b60123c66bf0739d1b2374b423d3061c..3e722dce6b21ab62535369f20afe5f0acd43838f 100644 +index 40366677b60123c66bf0739d1b2374b423d3061c..a2774e99726407d95011126ea2a272f08eaf0961 100644 --- a/browser/components/places/content/editBookmarkPanel.inc.xhtml +++ b/browser/components/places/content/editBookmarkPanel.inc.xhtml @@ -12,14 +12,15 @@ @@ -20,11 +20,10 @@ index 40366677b60123c66bf0739d1b2374b423d3061c..3e722dce6b21ab62535369f20afe5f0a