mirror of
https://github.com/zen-browser/desktop.git
synced 2026-05-27 23:35:09 +00:00
Compare commits
60 Commits
1.18.2b
...
space-rout
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15a908739d | ||
|
|
f842c945ce | ||
|
|
4d1d4ab1b6 | ||
|
|
2990de8366 | ||
|
|
76966ee1c3 | ||
|
|
4f9a932e77 | ||
|
|
f2603521e5 | ||
|
|
24f695c452 | ||
|
|
f5effd4dcd | ||
|
|
b5bb7d7c8b | ||
|
|
604365dd38 | ||
|
|
466d089fc0 | ||
|
|
e28a10f6a9 | ||
|
|
102be6cd90 | ||
|
|
6e1e1d061b | ||
|
|
43250d6d37 | ||
|
|
12f0c455d1 | ||
|
|
049c3c6f54 | ||
|
|
658ac94334 | ||
|
|
09a90099c7 | ||
|
|
051470f139 | ||
|
|
8f1cb88c11 | ||
|
|
3ef233a4c2 | ||
|
|
38fcd7e872 | ||
|
|
76f17c3a57 | ||
|
|
b5c2451525 | ||
|
|
ba2a854784 | ||
|
|
c9474cecc0 | ||
|
|
531be839c9 | ||
|
|
226486b973 | ||
|
|
5a137c95e5 | ||
|
|
e6154ceb99 | ||
|
|
1ea5d2fa6f | ||
|
|
97d5ebc21e | ||
|
|
442ec2a5d1 | ||
|
|
43ae672b44 | ||
|
|
84a54c9dbb | ||
|
|
6c53c3bf37 | ||
|
|
66686ab7f8 | ||
|
|
0c684a9bdb | ||
|
|
26dabffb96 | ||
|
|
ead077d16e | ||
|
|
a72fa3f79e | ||
|
|
33846dbce0 | ||
|
|
32fffaabe7 | ||
|
|
bf96b512cb | ||
|
|
32a42e797c | ||
|
|
29b8555c66 | ||
|
|
ab7698b16f | ||
|
|
cd0ef01fa1 | ||
|
|
41d97ddd21 | ||
|
|
a4386de00d | ||
|
|
28a2e8697a | ||
|
|
2ae623b15c | ||
|
|
8e7ce1c12b | ||
|
|
b5efe62739 | ||
|
|
e34ed3e882 | ||
|
|
658e35ebde | ||
|
|
1176f5ac8b | ||
|
|
4de01a9bc9 |
17
.github/workflows/sync-upstream.yml
vendored
17
.github/workflows/sync-upstream.yml
vendored
@@ -73,15 +73,13 @@ jobs:
|
||||
npm run sync
|
||||
fi
|
||||
|
||||
- name: Run formatter
|
||||
if: steps.check-upstream-branch.outputs.branch_exists == 'false'
|
||||
run: |
|
||||
sudo apt install python3-autopep8
|
||||
npm run pretty
|
||||
- name: Install autopep8
|
||||
run: sudo apt install python3-autopep8
|
||||
|
||||
- name: Check if any files changed
|
||||
id: git-check
|
||||
run: |
|
||||
npm run pretty
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
echo "files_changed=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
@@ -111,6 +109,15 @@ jobs:
|
||||
if: steps.git-check.outputs.files_changed == 'true'
|
||||
run: python3 scripts/import_external_tests.py || true
|
||||
|
||||
- name: Import external patches
|
||||
if: steps.git-check.outputs.files_changed == 'true'
|
||||
run: python3 scripts/import_external_patches.py || true
|
||||
|
||||
- name: Run formatter
|
||||
if: steps.check-upstream-branch.outputs.branch_exists == 'false'
|
||||
run: |
|
||||
npm run pretty
|
||||
|
||||
- name: Create pull request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
if: steps.git-check.outputs.files_changed == 'true'
|
||||
|
||||
@@ -37,5 +37,6 @@ src/zen/common/ZenEmojis.mjs
|
||||
|
||||
src/zen/split-view/zen-decks.css
|
||||
src/zen/workspaces/zen-workspaces.css
|
||||
src/zen/common/styles/zen-toolbar.css
|
||||
|
||||
*.inc
|
||||
|
||||
@@ -34,8 +34,8 @@ Zen is a firefox-based browser with the aim of pushing your productivity to a ne
|
||||
|
||||
### Firefox Versions
|
||||
|
||||
- [`Release`](https://zen-browser.app/download) - Is currently built using Firefox version `147.0.2`! 🚀
|
||||
- [`Twilight`](https://zen-browser.app/download?twilight) - Is currently built using Firefox version `RC 147.0.2`!
|
||||
- [`Release`](https://zen-browser.app/download) - Is currently built using Firefox version `147.0.3`! 🚀
|
||||
- [`Twilight`](https://zen-browser.app/download?twilight) - Is currently built using Firefox version `RC 147.0.3`!
|
||||
|
||||
### Contributing
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
7712a9ac90683965f71be525fe2827467632715d
|
||||
b1e00b74d3791a5a7bbd6ba3d32b69b60471e73b
|
||||
@@ -9,9 +9,6 @@ ac_add_options --with-app-basename=Zen
|
||||
# Localization (Must be an absolute path)
|
||||
ac_add_options --with-l10n-base="${topsrcdir}/browser/locales"
|
||||
|
||||
# See https://github.com/zen-browser/desktop/issues/11917 for future plans.
|
||||
# We should be removing this at some point and start supporting XDG dirs.
|
||||
ac_add_options --with-user-appdir=".${binName}"
|
||||
export MOZ_APP_BASENAME=Zen
|
||||
export MOZ_BRANDING_DIRECTORY=${brandingDir}
|
||||
export MOZ_OFFICIAL_BRANDING_DIRECTORY=${brandingDir}
|
||||
@@ -85,6 +82,11 @@ if test "$ZEN_RELEASE"; then
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
ac_add_options --disable-crashreporter
|
||||
|
||||
# Experimental flag, enabled only on nightly for Firefox.
|
||||
# Should bring in some nice performance improvements,
|
||||
# but may cause stability issues.
|
||||
ac_add_options --enable-replace-malloc
|
||||
fi
|
||||
|
||||
ac_add_options --enable-unverified-updates
|
||||
|
||||
262
docs/issue-metrics/2026_2026-01-01..2026-01-31.md
Normal file
262
docs/issue-metrics/2026_2026-01-01..2026-01-31.md
Normal file
@@ -0,0 +1,262 @@
|
||||
# Issue Metrics
|
||||
|
||||
| Metric | Average | Median | 90th percentile |
|
||||
| --- | --- | --- | ---: |
|
||||
| Time to first response | 14:19:40 | 2:07:00 | 1 day, 4:29:24 |
|
||||
| Time to close | 23:19:13 | 6:44:05 | 2 days, 5:35:23 |
|
||||
|
||||
| Metric | Count |
|
||||
| --- | ---: |
|
||||
| Number of items that remain open | 103 |
|
||||
| Number of items closed | 141 |
|
||||
| Total number of items created | 244 |
|
||||
|
||||
| Title | URL | Time to first response | Time to close |
|
||||
| --- | --- | --- | --- |
|
||||
| Filling in the search, query does not work with Ecosia | https://github.com/zen-browser/desktop/issues/12186 | None | None |
|
||||
| Workspaces are not synchronized between Zen on Windows 11 and macOS. | https://github.com/zen-browser/desktop/issues/12184 | 0:13:05 | 0:13:05 |
|
||||
| the 1st 2 workspaces aren't visible in the workspace bar at the bottom (SOLVED) | https://github.com/zen-browser/desktop/issues/12182 | None | 0:52:19 |
|
||||
| Broken web player and descript as part of page | https://github.com/zen-browser/desktop/issues/12181 | None | None |
|
||||
| Websites having wrong icons in history panel | https://github.com/zen-browser/desktop/issues/12179 | 4:54:50 | None |
|
||||
| Dragging and Dropping Tabs between Windows causes weird issues with Tab Sync enabled | https://github.com/zen-browser/desktop/issues/12178 | None | 16:59:50 |
|
||||
| Incorrect Text - Resetting an Essential Tab should be called "Reset Essential Tab" instead of "Reset Pinned Tab" | https://github.com/zen-browser/desktop/issues/12177 | None | None |
|
||||
| Windows management is broken - they keep cloning each other. | https://github.com/zen-browser/desktop/issues/12176 | 1:26:12 | 11:12:54 |
|
||||
| Application menu visual glitches on KDE Plasma 5.27.5 and Kwin | https://github.com/zen-browser/desktop/issues/12175 | None | None |
|
||||
| Middle mouse button does not delete tabs inside folders | https://github.com/zen-browser/desktop/issues/12174 | None | None |
|
||||
| Window Sync Extents to Unpinned and Non Essential Tabs (unexpected) | https://github.com/zen-browser/desktop/issues/12173 | 0:48:02 | None |
|
||||
| Clearing all tabs in window closes window | https://github.com/zen-browser/desktop/issues/12172 | 0:52:12 | None |
|
||||
| Disabling window sync prevents tabs from being re-named and dragging out tab to new window will use the blank default window instead the previous behaviour. | https://github.com/zen-browser/desktop/issues/12171 | None | None |
|
||||
| Update deleted all my tabs | https://github.com/zen-browser/desktop/issues/12170 | 0:40:34 | 21:14:31 |
|
||||
| Right-click > Move Tab does not always show your Workspaces | https://github.com/zen-browser/desktop/issues/12168 | 1 day, 4:29:24 | None |
|
||||
| background play isnt working | https://github.com/zen-browser/desktop/issues/12167 | None | None |
|
||||
| Windows 11 - Update to 1.18.3b loses all tabs and essentials | https://github.com/zen-browser/desktop/issues/12166 | 0:49:13 | 0:49:13 |
|
||||
| Zen wants to set itself as default browser after each update even if it already is | https://github.com/zen-browser/desktop/issues/12164 | None | None |
|
||||
| 1.18.3b AutoUpdate Lost all Tabs including Essentials | https://github.com/zen-browser/desktop/issues/12163 | 0:55:04 | 19:43:42 |
|
||||
| Gaming mouse's back/forward button keeps moving Workspaces instead of page | https://github.com/zen-browser/desktop/issues/12161 | 0:27:35 | 0:46:07 |
|
||||
| Dragging multiple tabs from one window to another flips their order | https://github.com/zen-browser/desktop/issues/12159 | None | None |
|
||||
| The pop-up UI button options for saving or saving passwords are not functional | https://github.com/zen-browser/desktop/issues/12158 | None | None |
|
||||
| I lost all my folder and essentials due to the uptdate | https://github.com/zen-browser/desktop/issues/12157 | 0:35:43 | 0:35:43 |
|
||||
| Dragging tabs between windows still doesn't work right | https://github.com/zen-browser/desktop/issues/12156 | 1:46:33 | None |
|
||||
| Discord Camera playback | https://github.com/zen-browser/desktop/issues/12155 | None | None |
|
||||
| Custom url homepage not working | https://github.com/zen-browser/desktop/issues/12154 | 13:36:48 | None |
|
||||
| Numerous "New Tabs" when restoring session | https://github.com/zen-browser/desktop/issues/12152 | 0:17:33 | None |
|
||||
| Feature Request: Allow manual editing of pinned tab URLs | https://github.com/zen-browser/desktop/issues/12151 | 1:19:36 | 1:19:36 |
|
||||
| "Find in page" bar has white background wth black theme | https://github.com/zen-browser/desktop/issues/12150 | None | 0:00:43 |
|
||||
| Open a local index.html with zen | https://github.com/zen-browser/desktop/issues/12149 | 4:53:15 | 8:41:06 |
|
||||
| No synchronization of tabs between computers | https://github.com/zen-browser/desktop/issues/12148 | 0:41:19 | 1:04:28 |
|
||||
| Cursor stuck as `default` everywhere after updating to 1.18.3b | https://github.com/zen-browser/desktop/issues/12145 | None | 21:06:24 |
|
||||
| An issue with custom keyboard shortcuts; Particular keys fail to work | https://github.com/zen-browser/desktop/issues/12144 | 13:30:14 | None |
|
||||
| 1.18.3b broke the drag to split tabs function (with a recording to show this in TROUBLE SHOOTING mode) | https://github.com/zen-browser/desktop/issues/12143 | 0:23:19 | None |
|
||||
| Loaded tabs are faded out in new windows | https://github.com/zen-browser/desktop/issues/12142 | 8:30:17 | None |
|
||||
| Window Sync with multi monitors is a nightmare. | https://github.com/zen-browser/desktop/issues/12141 | 0:36:59 | 8:04:12 |
|
||||
| Multiple Windows On Launch In Wayland | https://github.com/zen-browser/desktop/issues/12140 | 0:12:51 | None |
|
||||
| Update Broken, Cont. | https://github.com/zen-browser/desktop/issues/12139 | 14:23:05 | None |
|
||||
| Some Settings Are Not Persisting Between Restarts | https://github.com/zen-browser/desktop/issues/12138 | 2:27:50 | None |
|
||||
| "What's New" page text error for 1.18b | https://github.com/zen-browser/desktop/issues/12137 | 5:46:25 | 17:40:01 |
|
||||
| Grouping Tabs Together has become bugged on new update | https://github.com/zen-browser/desktop/issues/12136 | 2:38:32 | None |
|
||||
| Supabase Dashboard is not loading | https://github.com/zen-browser/desktop/issues/12135 | 6:13:09 | 20:45:26 |
|
||||
| Workspace bookmark | https://github.com/zen-browser/desktop/issues/12134 | None | None |
|
||||
| Broken Firefox Sync: Bookmarks no longer syncing between Zen Desktop and Firefox Mobile after recent update | https://github.com/zen-browser/desktop/issues/12133 | 1:22:35 | None |
|
||||
| 软件启动的时候会弹出两个窗口 | https://github.com/zen-browser/desktop/issues/12132 | 2:08:29 | 2:08:29 |
|
||||
| Latest Update deleted all my Tabs | https://github.com/zen-browser/desktop/issues/12131 | 0:08:05 | 0:07:30 |
|
||||
| Cannot drag tabs from window with 2 or more tabs into another window | https://github.com/zen-browser/desktop/issues/12130 | 0:06:58 | 0:06:58 |
|
||||
| Window sync completely breaks my workflow | https://github.com/zen-browser/desktop/issues/12127 | 0:11:09 | 1:42:54 |
|
||||
| Full screen video content cut off when browser window in full screen | https://github.com/zen-browser/desktop/issues/12126 | None | 0:39:59 |
|
||||
| Passkeys do not work on GitHub | https://github.com/zen-browser/desktop/issues/12125 | None | None |
|
||||
| Apple login does not work via apple.com's oauth API | https://github.com/zen-browser/desktop/issues/12124 | None | None |
|
||||
| "Open previous windows and tabs" setting breaks when zen.window-sync.prefer-unsynced-windows is set to false | https://github.com/zen-browser/desktop/issues/12121 | 0:54:22 | 8:23:30 |
|
||||
| Zen struggle rendering large DOM lists containing lots of child elements | https://github.com/zen-browser/desktop/issues/12119 | 2 days, 21:36:13 | None |
|
||||
| Drag and drop tabs to different workspaces between two different zen windows causes the tabs to disappear after restart | https://github.com/zen-browser/desktop/issues/12116 | 0:04:16 | None |
|
||||
| Windows Sync and Tabs | https://github.com/zen-browser/desktop/issues/12115 | 0:05:26 | 0:05:26 |
|
||||
| Loss of open tabs after update 1.18.x | https://github.com/zen-browser/desktop/issues/12114 | 1:10:05 | 1:59:02 |
|
||||
| Tab focus returns to parent tab instead of adjacent tab when closing multiple results | https://github.com/zen-browser/desktop/issues/12113 | 11:47:07 | 14:11:10 |
|
||||
| New window does not auto focus url bar with zen.urlbar.replace-newtab set to false | https://github.com/zen-browser/desktop/issues/12112 | None | None |
|
||||
| 1.18b completely breaks Simple Tab Groups | https://github.com/zen-browser/desktop/issues/12111 | 0:06:51 | 0:06:51 |
|
||||
| Essentials icon keep disappearing | https://github.com/zen-browser/desktop/issues/12110 | 0:13:16 | 0:13:16 |
|
||||
| Random Infinite Loading/Crashes when watching a YouTube video | https://github.com/zen-browser/desktop/issues/12109 | 1:23:12 | None |
|
||||
| Zen icon deleted after an update | https://github.com/zen-browser/desktop/issues/12108 | 0:08:52 | 0:08:52 |
|
||||
| Bug with folders with split tabs after update 1.18.2b (Mac) | https://github.com/zen-browser/desktop/issues/12107 | 0:17:10 | None |
|
||||
| Weird bug when repoen zen the tabs keeps recover | https://github.com/zen-browser/desktop/issues/12106 | 0:33:42 | None |
|
||||
| Notification can't be closed when tabs are on the right side (mailto notify) | https://github.com/zen-browser/desktop/issues/12104 | 2:40:15 | None |
|
||||
| Cannot move tab from one window to another | https://github.com/zen-browser/desktop/issues/12103 | 0:12:36 | 0:13:32 |
|
||||
| on Essential Tabs , when i recieve a message on whatsapp it gets hidden, i do get notification but it doesnt show | https://github.com/zen-browser/desktop/issues/12101 | 0:08:34 | 0:08:36 |
|
||||
| Continue where you let off for bookmarks | https://github.com/zen-browser/desktop/issues/12100 | 1:16:25 | 3:48:13 |
|
||||
| Essential tabs disappearing after excessive clicks | https://github.com/zen-browser/desktop/issues/12099 | 4:13:22 | 4:13:22 |
|
||||
| Enhanced Tracking Protection reverts back to strict on launch | https://github.com/zen-browser/desktop/issues/12096 | 7:40:37 | 19:27:51 |
|
||||
| Sidebar tab title color / contrast changed in v1.18 | https://github.com/zen-browser/desktop/issues/12095 | None | 0:13:40 |
|
||||
| New window does not open correct space. | https://github.com/zen-browser/desktop/issues/12094 | 0:01:55 | None |
|
||||
| Bug: Essentials tabs disappear after rapid activation | https://github.com/zen-browser/desktop/issues/12092 | 0:31:21 | 1:23:25 |
|
||||
| Tabs being cloned to all windows | https://github.com/zen-browser/desktop/issues/12088 | 0:06:01 | 0:47:56 |
|
||||
| Pinned extensions disappear when more than 1 is pinned | https://github.com/zen-browser/desktop/issues/12087 | 1 day, 14:00:23 | None |
|
||||
| Bookmark icons not showing properly | https://github.com/zen-browser/desktop/issues/12084 | 0:03:11 | None |
|
||||
| There is a problem with Zen when opening tabs: it is slow | https://github.com/zen-browser/desktop/issues/12083 | None | None |
|
||||
| Jump to a blank page after closing all normal tabs | https://github.com/zen-browser/desktop/issues/12081 | None | 1 day, 21:13:35 |
|
||||
| Dragging and Dropping tabs within the sidebar. Tab pops out as white box. | https://github.com/zen-browser/desktop/issues/12080 | 2:07:00 | None |
|
||||
| Essential tabs dissapear from sidebar UI | https://github.com/zen-browser/desktop/issues/12078 | 0:01:44 | 0:01:44 |
|
||||
| F6 doesn't float url bar | https://github.com/zen-browser/desktop/issues/12076 | 0:16:04 | 3:38:13 |
|
||||
| Blank window. Completely unusable | https://github.com/zen-browser/desktop/issues/12075 | 0:05:13 | 1:07:49 |
|
||||
| View Page Source opens in No Container Tab | https://github.com/zen-browser/desktop/issues/12074 | 0:04:07 | None |
|
||||
| Zen starting out blank with corrupted tabs | https://github.com/zen-browser/desktop/issues/12073 | 0:05:16 | 2 days, 10:11:43 |
|
||||
| Essentials becoming invisible / absent until browser restarted | https://github.com/zen-browser/desktop/issues/12072 | 0:06:59 | 0:06:59 |
|
||||
| Proxmox UI Shell renders unreadable. Previously worked. | https://github.com/zen-browser/desktop/issues/12071 | None | None |
|
||||
| Grid Split navigations is backwards | https://github.com/zen-browser/desktop/issues/12070 | 22:32:57 | 3 days, 7:21:01 |
|
||||
| Bookmarks no longer synchronize | https://github.com/zen-browser/desktop/issues/12069 | None | None |
|
||||
| Can't use MacOs specific video features (Portrait, Studio Light, Background) | https://github.com/zen-browser/desktop/issues/12068 | None | None |
|
||||
| Turning off zen.window-sync.enabled to false leads to broken new window | https://github.com/zen-browser/desktop/issues/12066 | 0:37:44 | 1:57:03 |
|
||||
| Can future versions please not clear out tabs and folder trees when updating/upgrade? | https://github.com/zen-browser/desktop/issues/12064 | None | 4:57:15 |
|
||||
| "New Blank Window" uses wrong theme color | https://github.com/zen-browser/desktop/issues/12062 | 9:49:13 | 11:15:18 |
|
||||
| [linux] Edit label/title for tab doesn't work | https://github.com/zen-browser/desktop/issues/12060 | 2:25:26 | 3 days, 18:16:00 |
|
||||
| Missing option to disable synced windows | https://github.com/zen-browser/desktop/issues/12059 | None | 0:01:21 |
|
||||
| Disable Window Sync option in settings? | https://github.com/zen-browser/desktop/issues/12058 | 0:12:41 | 0:12:41 |
|
||||
| Tab titles not updating when window sync is disabled | https://github.com/zen-browser/desktop/issues/12057 | 0:05:48 | 0:10:29 |
|
||||
| Essentials entry randomly disappeared from UI | https://github.com/zen-browser/desktop/issues/12056 | 0:12:56 | 0:12:56 |
|
||||
| Pinned tabs not resseting on startup | https://github.com/zen-browser/desktop/issues/12055 | 2:00:07 | 2:30:05 |
|
||||
| [Wayland] Zen browser shows white blank panel on startup | https://github.com/zen-browser/desktop/issues/12054 | 1:24:35 | 1 day, 12:37:36 |
|
||||
| [Tab Sync] Tab in Glance mode opens as regular tab on other window. | https://github.com/zen-browser/desktop/issues/12051 | 1 day, 19:56:04 | None |
|
||||
| workspace tabs desync across windows | https://github.com/zen-browser/desktop/issues/12050 | 0:11:59 | None |
|
||||
| Essential tab stop working | https://github.com/zen-browser/desktop/issues/12045 | 0:46:10 | 0:46:10 |
|
||||
| PWA apps render issue | https://github.com/zen-browser/desktop/issues/12044 | 1:32:16 | 3 days, 1:18:16 |
|
||||
| MacOS - Wrong tab selected when going backwards | https://github.com/zen-browser/desktop/issues/12043 | 0:04:04 | None |
|
||||
| Problem with important tabs | https://github.com/zen-browser/desktop/issues/12042 | 2 days, 4:15:21 | 2 days, 20:49:00 |
|
||||
| Pinned and essential tabs randomly disappear | https://github.com/zen-browser/desktop/issues/12040 | 0:34:50 | 0:34:50 |
|
||||
| Sidebar overflows in compact mode | https://github.com/zen-browser/desktop/issues/12039 | 1 day, 4:05:41 | None |
|
||||
| Dragging tabs between worksapce is buggy [I think due to sync] | https://github.com/zen-browser/desktop/issues/12037 | 5 days, 11:35:22 | 5 days, 11:35:22 |
|
||||
| Sidebar doesn’t close automatically after creating a new tab in Compact Mode | https://github.com/zen-browser/desktop/issues/12036 | 2 days, 6:04:10 | None |
|
||||
| The extension items in the context menu multiplying with every right click | https://github.com/zen-browser/desktop/issues/12035 | 3:50:26 | None |
|
||||
| Disabling zen.window-sync.enabled breaks "Open previous windows and tabs" | https://github.com/zen-browser/desktop/issues/12034 | 4:38:30 | 6:11:16 |
|
||||
| Tab cannot be grabbed and taken into a different Zen browser instance | https://github.com/zen-browser/desktop/issues/12032 | 0:11:57 | 1:21:44 |
|
||||
| Window sync with zoom | https://github.com/zen-browser/desktop/issues/12031 | 3:33:29 | 1 day, 17:09:02 |
|
||||
| New Window doesn't work with window sync disabled. | https://github.com/zen-browser/desktop/issues/12030 | None | 1:21:07 |
|
||||
| Move to space not listed in context menu | https://github.com/zen-browser/desktop/issues/12029 | 1:28:17 | 1:28:17 |
|
||||
| All my workspaces and tabs just gone after update, wtf ? :) | https://github.com/zen-browser/desktop/issues/12028 | 0:31:31 | 1:41:41 |
|
||||
| Global menu show but unresponsive. | https://github.com/zen-browser/desktop/issues/12024 | 0:06:03 | 6 days, 1:49:53 |
|
||||
| Debian 13 | Passkey doesn't show QR code | https://github.com/zen-browser/desktop/issues/12022 | 10:08:54 | None |
|
||||
| Performance: Swiping across spaces with multiple tabs open is laggy | https://github.com/zen-browser/desktop/issues/12020 | 0:09:27 | 0:09:27 |
|
||||
| Move to Space | https://github.com/zen-browser/desktop/issues/12019 | 0:08:00 | 0:08:00 |
|
||||
| [UI Error] Zen Browser Settings UI Error | https://github.com/zen-browser/desktop/issues/12014 | 0:41:54 | 6:44:05 |
|
||||
| Full-Screen PIP Mode Retains Dimmed State Indefinitely Due to Hover and System Inactivity | https://github.com/zen-browser/desktop/issues/12013 | None | None |
|
||||
| "Check for Updates" Not Working | https://github.com/zen-browser/desktop/issues/12012 | 1:54:04 | 1:54:09 |
|
||||
| Website lolalytics.com not working properly after updating to 1.18.1b | https://github.com/zen-browser/desktop/issues/12011 | 10:35:46 | 11:32:35 |
|
||||
| No "Open a new Blank Window" action when right-clicking zen on taskbar | https://github.com/zen-browser/desktop/issues/12010 | 9:50:45 | None |
|
||||
| Inconsistant capitalization in application menu | https://github.com/zen-browser/desktop/issues/12009 | None | 0:15:37 |
|
||||
| Disable window/tab sync by default | https://github.com/zen-browser/desktop/issues/12008 | 0:03:34 | 17:22:46 |
|
||||
| Sync not working + pinned tabs do not resert url | https://github.com/zen-browser/desktop/issues/12006 | 0:15:54 | 7:59:09 |
|
||||
| Some UI elements not renderring correctly | https://github.com/zen-browser/desktop/issues/12005 | 3:40:46 | 4:36:15 |
|
||||
| installer prolbem | https://github.com/zen-browser/desktop/issues/12004 | 2:13:28 | 2:13:28 |
|
||||
| Issues with Sidebar Dragging Exiting Full-Screen & Legacy Ctrl+Tab Behavior | https://github.com/zen-browser/desktop/issues/12003 | 4:33:38 | None |
|
||||
| Cannot Rename “New Folder” in the Sidebar | https://github.com/zen-browser/desktop/issues/12002 | 0:58:42 | 1:48:21 |
|
||||
| Custom font doesn't work | https://github.com/zen-browser/desktop/issues/12001 | 1 day, 8:53:16 | 1 day, 8:53:16 |
|
||||
| Windows accent coloring issue with zen | https://github.com/zen-browser/desktop/issues/12000 | 1:11:28 | 1:11:28 |
|
||||
| Disabling zen.window-sync.enabled breaks new zen instances | https://github.com/zen-browser/desktop/issues/11999 | 4:34:06 | 22:44:50 |
|
||||
| Pinned tabs don't scale: hundreds of pins freeze browser | https://github.com/zen-browser/desktop/issues/11997 | 6:50:35 | 1 day, 13:33:03 |
|
||||
| All tabs are gone (also pinned) when updating to 1.18b | https://github.com/zen-browser/desktop/issues/11994 | 4:42:08 | None |
|
||||
| "blank window" at startup | https://github.com/zen-browser/desktop/issues/11993 | 0:02:32 | 0:52:40 |
|
||||
| Crashing when playing WASMGC game | https://github.com/zen-browser/desktop/issues/11990 | 0:31:55 | None |
|
||||
| Pinned Tabs disappearing/invisible | https://github.com/zen-browser/desktop/issues/11989 | 11:31:45 | 11:31:45 |
|
||||
| Zen process opens but the window doesn't | https://github.com/zen-browser/desktop/issues/11985 | 0:22:24 | None |
|
||||
| Zen has recently got really inconsistent performance (especially after the last few updates). | https://github.com/zen-browser/desktop/issues/11982 | 0:52:04 | None |
|
||||
| Twitch.tv Video Streams Not Loading | https://github.com/zen-browser/desktop/issues/11980 | 0:19:27 | None |
|
||||
| Page rendering is blank white | https://github.com/zen-browser/desktop/issues/11979 | 15:04:14 | 15:04:14 |
|
||||
| Zen is unusable on Cosmic Desktop Environment (unable to remove a checkbox that spawns and hinders using the browser) | https://github.com/zen-browser/desktop/issues/11978 | 0:42:40 | 17:46:00 |
|
||||
| Searching with # is not searching bookmarks by tag or title | https://github.com/zen-browser/desktop/issues/11976 | 1:54:07 | 11:45:13 |
|
||||
| Conflict Between Browser Page Search Shortcut and Confluence Search | https://github.com/zen-browser/desktop/issues/11975 | None | None |
|
||||
| Updater repeatedly reinstalls latest twilight build despite no version change. | https://github.com/zen-browser/desktop/issues/11974 | 0:19:47 | 6:53:06 |
|
||||
| Randomly Control button stop functioning | https://github.com/zen-browser/desktop/issues/11972 | None | None |
|
||||
| Low refresh rate on Zen Windows version after OS update | https://github.com/zen-browser/desktop/issues/11967 | 21:19:01 | None |
|
||||
| Switching workspaces to a split view will cause the area surround the view to turn black for a second | https://github.com/zen-browser/desktop/issues/11965 | 17:19:30 | None |
|
||||
| [Bug] Previous session permanently lost after closing and reopening Zen Browser | https://github.com/zen-browser/desktop/issues/11964 | 4:00:54 | 4:01:24 |
|
||||
| Closing a normal zen window when an incognito zen browser is opened, removes all the tabs across all my workspaces. | https://github.com/zen-browser/desktop/issues/11963 | 2:10:13 | 2:10:13 |
|
||||
| Only sidebar layout -- Always show bookmarks tool bar + window buttons | https://github.com/zen-browser/desktop/issues/11962 | 0:06:53 | 3:10:47 |
|
||||
| Zen randomly crashes on macOS | https://github.com/zen-browser/desktop/issues/11958 | 3:36:36 | None |
|
||||
| Essentials and pinned tabs don't load automatically on open | https://github.com/zen-browser/desktop/issues/11957 | 12:57:52 | 12:57:52 |
|
||||
| Readme reports Firefox 147.0.1 for Release but latest release 1.17.15b (2025-12-20) is 146.0.1 | https://github.com/zen-browser/desktop/issues/11952 | 8:47:04 | 8:47:03 |
|
||||
| Non-default container indicator not showing in workspace | https://github.com/zen-browser/desktop/issues/11951 | 0:13:01 | None |
|
||||
| Zen not displaying websites on Intel HD graphics 2000 | https://github.com/zen-browser/desktop/issues/11950 | None | None |
|
||||
| Private window tabs are mirrored in the main (non-private) window | https://github.com/zen-browser/desktop/issues/11949 | 2:34:54 | 4:47:55 |
|
||||
| Media session metadata (title/artist/cover) does not update on site without page refresh | https://github.com/zen-browser/desktop/issues/11948 | 6:32:56 | 1 day, 6:51:54 |
|
||||
| Nvidia overlay "Plugin-container is preventing the desktop capture" | https://github.com/zen-browser/desktop/issues/11947 | None | None |
|
||||
| Login to self-hosted Bitwarden fails after initialization in multi-account setting | https://github.com/zen-browser/desktop/issues/11946 | 1 day, 14:57:08 | None |
|
||||
| Accessing any URL under bitbucket.org returns 404 | https://github.com/zen-browser/desktop/issues/11944 | 2:26:35 | 1 day, 20:58:15 |
|
||||
| Acrylic turns grey | https://github.com/zen-browser/desktop/issues/11937 | 0:01:44 | None |
|
||||
| lang change | https://github.com/zen-browser/desktop/issues/11934 | 2:27:46 | 3:29:15 |
|
||||
| MX Master 3 Forward/Back mouse buttons don't work if zen.workspaces.swipe-actions is false | https://github.com/zen-browser/desktop/issues/11923 | 1:53:09 | 1:53:09 |
|
||||
| Tabs UI bug | https://github.com/zen-browser/desktop/issues/11922 | None | None |
|
||||
| Positioning of titlebar window control buttons | https://github.com/zen-browser/desktop/issues/11918 | 11:28:41 | 11:28:41 |
|
||||
| Zen won't follow XDG base directories | https://github.com/zen-browser/desktop/issues/11917 | 12:43:08 | None |
|
||||
| Titlebar expands on hover even if Titlebar setting is Disabled from "Configure Toolbar" in Sidebar only mode of look and feel. | https://github.com/zen-browser/desktop/issues/11915 | None | None |
|
||||
| Multiple window sessions result in same tabs open in all windows | https://github.com/zen-browser/desktop/issues/11914 | 1 day, 1:41:36 | 1 day, 1:41:36 |
|
||||
| Misplaced Tab (Placed a tab above the new tab button but below the line that separates the pinned tabs) | https://github.com/zen-browser/desktop/issues/11911 | None | 4:09:21 |
|
||||
| Sidebar width inconsistency | https://github.com/zen-browser/desktop/issues/11909 | None | None |
|
||||
| Cannot expand / fullscreen twitter videos | https://github.com/zen-browser/desktop/issues/11908 | 2 days, 5:35:23 | 2 days, 5:35:23 |
|
||||
| Menu shows unsecure connections as secure | https://github.com/zen-browser/desktop/issues/11905 | 2:21:24 | 3:35:25 |
|
||||
| Top Toolbar appearing when using shortcut "Toggle Sidebar's Width" | https://github.com/zen-browser/desktop/issues/11903 | 5:08:25 | 5:08:25 |
|
||||
| Only shows default icons for Google Messages for web | https://github.com/zen-browser/desktop/issues/11902 | None | 2:39:30 |
|
||||
| The default section disappear from dot list at the below of the tab when swiching spaces | https://github.com/zen-browser/desktop/issues/11901 | 0:50:18 | None |
|
||||
| Context menu partially hidden when right-clicking on a Bookmarks folder in the toolbar | https://github.com/zen-browser/desktop/issues/11898 | None | None |
|
||||
| Refined Github(extension): Issues interface with notification header flickers / flashes | https://github.com/zen-browser/desktop/issues/11896 | None | None |
|
||||
| Glance should work only for links | https://github.com/zen-browser/desktop/issues/11895 | None | 7:53:12 |
|
||||
| Auto Unload Does Not And Has Never Unloaded a Single Tab Ever. | https://github.com/zen-browser/desktop/issues/11894 | None | 6:58:48 |
|
||||
| Visual Bug: Line through sidebar and settings page | https://github.com/zen-browser/desktop/issues/11893 | None | 12:24:36 |
|
||||
| 1password integration - not working | https://github.com/zen-browser/desktop/issues/11892 | 2:39:46 | 13:40:23 |
|
||||
| Hardware acceleration worse on Zen vs others (CachyOS - NVIDIA - Wayland) | https://github.com/zen-browser/desktop/issues/11890 | 2:18:58 | 8:44:12 |
|
||||
| Some tabs (inside a folder) are not drawn in the sidebar | https://github.com/zen-browser/desktop/issues/11888 | 18:13:05 | 18:13:05 |
|
||||
| (macos) (twilight) pinning splitview tabs in folders causes addl tab group labels on restart/update | https://github.com/zen-browser/desktop/issues/11887 | None | 23:27:16 |
|
||||
| How can I achieve window transparency on Windows (so that I can see through to the windows or desktop behind it)?/如何实现Windows下窗口透明化(可以看到后面的窗口或桌面) | https://github.com/zen-browser/desktop/issues/11885 | 11:12:00 | 11:12:00 |
|
||||
| Form validation checkbox message is white text on white background | https://github.com/zen-browser/desktop/issues/11884 | None | None |
|
||||
| Fullscreen with F11 doesn't work as intended | https://github.com/zen-browser/desktop/issues/11883 | 6:30:42 | 6:30:46 |
|
||||
| PiP window stays open empty and buttons don’t work | https://github.com/zen-browser/desktop/issues/11881 | None | None |
|
||||
| When switching browser layouts, extensions fixed to the toolbar may have display bugs | https://github.com/zen-browser/desktop/issues/11880 | None | 6:31:27 |
|
||||
| Zen startup window has a transition from dark background (light background in light mode) + a flash before the mica kicks on windows 11. | https://github.com/zen-browser/desktop/issues/11876 | 1 day, 22:21:29 | None |
|
||||
| Zen Hangs/Crashes - Have not been able to use for several months. | https://github.com/zen-browser/desktop/issues/11875 | 2 days, 0:58:56 | None |
|
||||
| Settings modal is not in the right place! | https://github.com/zen-browser/desktop/issues/11873 | None | None |
|
||||
| Macos: extention pop-ups open up at a different desktop in fullscreen | https://github.com/zen-browser/desktop/issues/11872 | 7:25:14 | 7:25:14 |
|
||||
| Close Tab shortcut can close the window | https://github.com/zen-browser/desktop/issues/11871 | 2 days, 6:59:58 | 2 days, 6:59:58 |
|
||||
| When on the login page, the extension icon in the address bar cannot be clicked | https://github.com/zen-browser/desktop/issues/11870 | 2 days, 8:04:14 | 19 days, 3:16:59 |
|
||||
| Showing multiple empthy pages | https://github.com/zen-browser/desktop/issues/11869 | 4:22:38 | None |
|
||||
| Control + click is not opening links in a new tab. | https://github.com/zen-browser/desktop/issues/11868 | 3 days, 21:19:59 | None |
|
||||
| Folders and tabs of a workspace are not synced. | https://github.com/zen-browser/desktop/issues/11865 | 1:58:13 | 1:58:13 |
|
||||
| No save button | https://github.com/zen-browser/desktop/issues/11864 | 0:15:11 | None |
|
||||
| No Icon For Files | https://github.com/zen-browser/desktop/issues/11860 | 5:02:04 | 20:21:37 |
|
||||
| Compatibility issue with aarch64 AppImage starting from v1.17b (GLIBCXX_3.4.26 not found) | https://github.com/zen-browser/desktop/issues/11859 | None | None |
|
||||
| Adding New Bookmark in Compact Mode No Longer Pops Up Edit Panel | https://github.com/zen-browser/desktop/issues/11858 | 1 day, 18:54:21 | None |
|
||||
| 什么时候能支持网页驱动 | https://github.com/zen-browser/desktop/issues/11857 | 12:28:29 | 12:28:29 |
|
||||
| Workspace Switching Becomes Laggy with 4+ Workspaces and many pinned Tabs on Windows (NVIDIA GPU). | https://github.com/zen-browser/desktop/issues/11851 | 2:00:50 | None |
|
||||
| Closing a recently opened tab returns to the top tab, not the previously focused tab | https://github.com/zen-browser/desktop/issues/11845 | 19:10:53 | 1 day, 17:02:53 |
|
||||
| Wrong italian translation of "Workspace forward" in shortcuts settings | https://github.com/zen-browser/desktop/issues/11841 | 1:17:18 | None |
|
||||
| Cannot close pinned tabs | https://github.com/zen-browser/desktop/issues/11838 | 0:21:08 | 0:23:33 |
|
||||
| Copy URL shortcut does not copy URL before page has loaded | https://github.com/zen-browser/desktop/issues/11835 | None | None |
|
||||
| Extensions not showing up in toolbar. | https://github.com/zen-browser/desktop/issues/11834 | 1:33:29 | 9:20:29 |
|
||||
| Multiple duplicated Bookmarks | https://github.com/zen-browser/desktop/issues/11832 | None | None |
|
||||
| [BUG] Closing and re-opening zen twighlight turns a bunch of tabs into 'New Tab's | https://github.com/zen-browser/desktop/issues/11831 | 15:57:31 | 7 days, 8:27:19 |
|
||||
| Indent issue on active pinned tab in collapsed workspace | https://github.com/zen-browser/desktop/issues/11830 | 17:46:11 | 1 day, 6:07:21 |
|
||||
| High Ram Usage | https://github.com/zen-browser/desktop/issues/11828 | None | 0:20:29 |
|
||||
| Unable to install extentions in compact mode | https://github.com/zen-browser/desktop/issues/11827 | None | 1:11:29 |
|
||||
| Extension icons display inconsitently when switching toolbar modes or resizing window | https://github.com/zen-browser/desktop/issues/11826 | 2:31:13 | None |
|
||||
| MS Entra auth not working | https://github.com/zen-browser/desktop/issues/11825 | 3:14:28 | 20:29:41 |
|
||||
| "Restore pinned tabs to their originally pinned URL on startup' option doesn't reset Pinned Tabs go back to Originally Pinned URL, i.e. doesn't reset them | https://github.com/zen-browser/desktop/issues/11823 | 2 days, 12:40:16 | None |
|
||||
| Crashes when signing into aws console MFA passkey via lastpassword | https://github.com/zen-browser/desktop/issues/11820 | None | None |
|
||||
| Using the dev console in glance causes weird ui | https://github.com/zen-browser/desktop/issues/11815 | 1:43:58 | None |
|
||||
| The VS Code integrated extension “Live Server” does not automatically detect the Zen Browser, even when it is set as the default browser. | https://github.com/zen-browser/desktop/issues/11813 | 2:56:35 | 2 days, 12:21:43 |
|
||||
| Ctrl+T does not open new tab if shortcuts are removed | https://github.com/zen-browser/desktop/issues/11811 | 0:40:23 | None |
|
||||
| Sidebar title is overlapping with essential tabs after screen unlock | https://github.com/zen-browser/desktop/issues/11808 | None | 15:50:26 |
|
||||
| button alignment does not change in pop-up window | https://github.com/zen-browser/desktop/issues/11805 | 0:10:14 | None |
|
||||
| "Focus on <space>" action not available | https://github.com/zen-browser/desktop/issues/11804 | 0:03:34 | 1 day, 0:35:28 |
|
||||
| Split View and Floating URL bugs when a Youtube video is in Full Screen and Ctrl + Shift + * is pressed. | https://github.com/zen-browser/desktop/issues/11803 | None | 7 days, 0:58:59 |
|
||||
| Trackpad diagonal scroll unintentionally switches workspaces instead of scrolling tabs | https://github.com/zen-browser/desktop/issues/11802 | 2:20:42 | None |
|
||||
| New tab opens when Alt+Tabbing or pressing Windows key while YouTube is playing | https://github.com/zen-browser/desktop/issues/11801 | 8:57:44 | None |
|
||||
| Broken Installer (fixed) | https://github.com/zen-browser/desktop/issues/11800 | None | 1 day, 22:57:03 |
|
||||
| subfolder collapse state issue when collapsing pinned area | https://github.com/zen-browser/desktop/issues/11799 | 11:27:53 | 1 day, 12:52:10 |
|
||||
| Glance opens a new window for local file URLs (file://) | https://github.com/zen-browser/desktop/issues/11797 | None | None |
|
||||
| acronis.com nginx a header or cookie larger than permitted | https://github.com/zen-browser/desktop/issues/11795 | None | None |
|
||||
| Cannot listen to songs using the spotify integration on Musixmatch for lyric syncing in Zen | https://github.com/zen-browser/desktop/issues/11792 | 0:15:31 | 0:15:31 |
|
||||
| Adding Split Tab Groups to a folder Makes the folder disappear | https://github.com/zen-browser/desktop/issues/11791 | 15 days, 4:38:37 | 15 days, 4:38:37 |
|
||||
| Clear tabs button's separator is missing on Linux | https://github.com/zen-browser/desktop/issues/11789 | None | 3 days, 10:41:55 |
|
||||
| [Twilight] Cannot add tab to bottom of folder | https://github.com/zen-browser/desktop/issues/11788 | 21:08:12 | 21:08:12 |
|
||||
| Flathub version doesn’t work on Debian 13 | https://github.com/zen-browser/desktop/issues/11787 | 25 days, 12:50:21 | None |
|
||||
| Split View sidebar shows extra tab after restoring a closed tab (Ctrl+Shift+T) | https://github.com/zen-browser/desktop/issues/11785 | None | None |
|
||||
| Cursor moved far right of window does not grab scrollbar when window is maximised | https://github.com/zen-browser/desktop/issues/11783 | 6:07:23 | 6:07:23 |
|
||||
| HMR Not Working Correctly for Frontend Development | https://github.com/zen-browser/desktop/issues/11782 | 7:57:34 | 9:05:06 |
|
||||
| Failing to obtain location | https://github.com/zen-browser/desktop/issues/11781 | 15:43:36 | 1 day, 17:23:10 |
|
||||
|
||||
_This report was generated with the [Issue Metrics Action](https://github.com/github/issue-metrics)_
|
||||
Search query used to find these items: `repo:zen-browser/desktop is:issue created:2026-01-01..2026-01-31`
|
||||
@@ -314,4 +314,4 @@ zen-devtools-toggle-storage-shortcut = Commuta l'emmagatzematge
|
||||
zen-devtools-toggle-dom-shortcut = Commuta el DOM
|
||||
zen-devtools-toggle-accessibility-shortcut = Commuta l'accessibilitat
|
||||
zen-close-all-unpinned-tabs-shortcut = Tanca totes les pestanyes no fixades
|
||||
zen-new-unsynced-window-shortcut = Nova finestra no sincronitzada
|
||||
zen-new-unsynced-window-shortcut = Nova finestra en blanc
|
||||
|
||||
@@ -19,4 +19,4 @@ zen-menubar-appearance-light =
|
||||
zen-menubar-appearance-dark =
|
||||
.label = Fosca
|
||||
zen-menubar-new-unsynced-window =
|
||||
.label = New Blank Window
|
||||
.label = Nova finestra en blanc
|
||||
|
||||
@@ -314,4 +314,4 @@ zen-devtools-toggle-storage-shortcut = Toglo Storio
|
||||
zen-devtools-toggle-dom-shortcut = Toglo DOM
|
||||
zen-devtools-toggle-accessibility-shortcut = Toglo Hygyrchedd
|
||||
zen-close-all-unpinned-tabs-shortcut = Cau Pob Tab Heb ei Binio
|
||||
zen-new-unsynced-window-shortcut = Ffenestr Newydd Heb ei Chydweddu
|
||||
zen-new-unsynced-window-shortcut = Ffenestr Wag Newydd
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
zen-panel-ui-current-profile-text = proffil cyfredol
|
||||
unified-extensions-description = Mae ychwanegiadau'n cael ei defnyddio er mwyn ychwanegu fwy o weithrediadau i { -brand-short-name }.
|
||||
zen-panel-ui-current-profile-text = y proffil cyfredol
|
||||
unified-extensions-description = Mae estyniadau'n cael ei defnyddio er mwyn ychwanegu fwy o swyddogaeth i { -brand-short-name }.
|
||||
tab-context-zen-reset-pinned-tab =
|
||||
.label = Ailosod Tab wedi'i Binio
|
||||
.accesskey = A
|
||||
@@ -109,7 +109,7 @@ zen-sidebar-notification-updated-tooltip =
|
||||
zen-sidebar-notification-restart-safe-mode-label = Rhywbeth wedi torri?
|
||||
zen-sidebar-notification-restart-safe-mode-tooltip =
|
||||
.title = Ailgychwyn yn y Modd Diogel
|
||||
zen-window-sync-migration-dialog-title = Keep Your Windows in Sync
|
||||
zen-window-sync-migration-dialog-message = Zen now syncs windows on the same device, so changes in one window are reflected across the others instantly.
|
||||
zen-window-sync-migration-dialog-learn-more = Learn More
|
||||
zen-window-sync-migration-dialog-accept = Got It
|
||||
zen-window-sync-migration-dialog-title = Cadw Eich Ffenestr Wedi'u Cydweddu
|
||||
zen-window-sync-migration-dialog-message = Mae Zen bellach yn cydweddu ffenestri ar yr un ddyfais, felly mae newidiadau mewn un ffenestr yn cael eu dangos ar y lleill yn syth.
|
||||
zen-window-sync-migration-dialog-learn-more = Dysgu Rhagor
|
||||
zen-window-sync-migration-dialog-accept = Iawn
|
||||
|
||||
@@ -19,4 +19,4 @@ zen-menubar-appearance-light =
|
||||
zen-menubar-appearance-dark =
|
||||
.label = Tywyll
|
||||
zen-menubar-new-unsynced-window =
|
||||
.label = New Blank Window
|
||||
.label = Ffenestr Wag Newydd
|
||||
|
||||
@@ -59,6 +59,9 @@ zen-tabs-select-recently-used-on-close =
|
||||
zen-tabs-close-on-back-with-no-history =
|
||||
.label = Close tab and switch to its owner tab (or most recently used tab) when going back with no history
|
||||
|
||||
zen-settings-workspaces-sync-unpinned-tabs =
|
||||
.label = Sync only pinned tabs in workspaces
|
||||
|
||||
zen-tabs-cycle-by-attribute =
|
||||
.label = Ctrl+Tab cycles within Essential or Workspace tabs only
|
||||
zen-tabs-cycle-ignore-pending-tabs =
|
||||
|
||||
@@ -6,7 +6,11 @@ zen-panel-ui-current-profile-text = current profile
|
||||
|
||||
unified-extensions-description = Extensions are used to bring more extra functionality into { -brand-short-name }.
|
||||
tab-context-zen-reset-pinned-tab =
|
||||
.label = Reset Pinned Tab
|
||||
.label =
|
||||
{ $isEssential ->
|
||||
[true] Reset Essential Tab
|
||||
*[false] Reset Pinned Tab
|
||||
}
|
||||
.accesskey = R
|
||||
tab-context-zen-add-essential =
|
||||
.label = Add to Essentials
|
||||
@@ -16,7 +20,11 @@ tab-context-zen-remove-essential =
|
||||
.label = Remove from Essentials
|
||||
.accesskey = R
|
||||
tab-context-zen-replace-pinned-url-with-current =
|
||||
.label = Replace Pinned URL with Current
|
||||
.label =
|
||||
{ $isEssential ->
|
||||
[true] Replace Essential URL with Current
|
||||
*[false] Replace Pinned URL with Current
|
||||
}
|
||||
.accesskey = C
|
||||
tab-context-zen-edit-title =
|
||||
.label = Change Label...
|
||||
@@ -137,3 +145,7 @@ zen-window-sync-migration-dialog-title = Keep Your Windows in Sync
|
||||
zen-window-sync-migration-dialog-message = Zen now syncs windows on the same device, so changes in one window are reflected across the others instantly.
|
||||
zen-window-sync-migration-dialog-learn-more = Learn More
|
||||
zen-window-sync-migration-dialog-accept = Got It
|
||||
|
||||
zen-appmenu-new-blank-window =
|
||||
.label = New blank window
|
||||
|
||||
|
||||
@@ -22,5 +22,5 @@ zen-menubar-appearance-light =
|
||||
zen-menubar-appearance-dark =
|
||||
.label = Dark
|
||||
|
||||
zen-menubar-new-unsynced-window =
|
||||
.label = New blank window
|
||||
zen-menubar-new-blank-window =
|
||||
.label = New Blank Window
|
||||
|
||||
@@ -19,4 +19,4 @@ zen-menubar-appearance-light =
|
||||
zen-menubar-appearance-dark =
|
||||
.label = Sombre
|
||||
zen-menubar-new-unsynced-window =
|
||||
.label = New Blank Window
|
||||
.label = Nouvelle fenêtre non synchronisée
|
||||
|
||||
@@ -19,4 +19,4 @@ zen-menubar-appearance-light =
|
||||
zen-menubar-appearance-dark =
|
||||
.label = Dorcha
|
||||
zen-menubar-new-unsynced-window =
|
||||
.label = New Blank Window
|
||||
.label = Fuinneog Nua Bán
|
||||
|
||||
@@ -19,4 +19,4 @@ zen-menubar-appearance-light =
|
||||
zen-menubar-appearance-dark =
|
||||
.label = כהה
|
||||
zen-menubar-new-unsynced-window =
|
||||
.label = New Blank Window
|
||||
.label = חלון ריק חדש
|
||||
|
||||
@@ -19,4 +19,4 @@ zen-menubar-appearance-light =
|
||||
zen-menubar-appearance-dark =
|
||||
.label = Sötét
|
||||
zen-menubar-new-unsynced-window =
|
||||
.label = New Blank Window
|
||||
.label = Új üres lap
|
||||
|
||||
@@ -49,8 +49,8 @@ zen-tabs-close-on-back-with-no-history =
|
||||
zen-tabs-cycle-by-attribute =
|
||||
.label = Ctrl+Tab berputar hanya dalam tab Esensial atau Ruang Kerja
|
||||
zen-tabs-cycle-ignore-pending-tabs =
|
||||
.label = Ignore Pending tabs when cycling with Ctrl+Tab
|
||||
zen-tabs-cycle-by-attribute-warning = Ctrl+Tab will cycle by recently used order, as it is enabled
|
||||
.label = Lewati tab tak termuat saat beralih dengan Ctrl+Tab
|
||||
zen-tabs-cycle-by-attribute-warning = Ctrl+Tab akan beralih berdasarkan urutan terakhir digunakan
|
||||
zen-look-and-feel-compact-toolbar-themed =
|
||||
.label = Gunakan latar belakang bertema untuk bilah atas dalam mode ringkas
|
||||
zen-workspace-continue-where-left-off =
|
||||
@@ -314,4 +314,4 @@ zen-devtools-toggle-storage-shortcut = Ubah Penyimpanan
|
||||
zen-devtools-toggle-dom-shortcut = Ubah DOM
|
||||
zen-devtools-toggle-accessibility-shortcut = Ubah Aksesibilitas
|
||||
zen-close-all-unpinned-tabs-shortcut = Tutup Semua Tab yang Tidak Disematkan
|
||||
zen-new-unsynced-window-shortcut = New Unsynced Window
|
||||
zen-new-unsynced-window-shortcut = Jendela Kosong Baru
|
||||
|
||||
@@ -60,8 +60,8 @@ zen-site-data-settings = Pengaturan
|
||||
zen-generic-manage = Kelola
|
||||
zen-generic-more = Selengkapnya
|
||||
zen-generic-next = Lanjut
|
||||
zen-essentials-promo-label = Add to Essentials
|
||||
zen-essentials-promo-sublabel = Keep your favorite tabs just a click away
|
||||
zen-essentials-promo-label = Tambahkan ke Essentials
|
||||
zen-essentials-promo-sublabel = Akses tab favorit Anda hanya dengan sekali klik
|
||||
# These labels will be used for the site data panel settings
|
||||
zen-site-data-setting-allow = Diizinkan
|
||||
zen-site-data-setting-block = Diblokir
|
||||
@@ -109,7 +109,7 @@ zen-sidebar-notification-updated-tooltip =
|
||||
zen-sidebar-notification-restart-safe-mode-label = Ada yang rusak?
|
||||
zen-sidebar-notification-restart-safe-mode-tooltip =
|
||||
.title = Mulai Ulang dalam Mode Aman
|
||||
zen-window-sync-migration-dialog-title = Keep Your Windows in Sync
|
||||
zen-window-sync-migration-dialog-message = Zen now syncs windows on the same device, so changes in one window are reflected across the others instantly.
|
||||
zen-window-sync-migration-dialog-learn-more = Learn More
|
||||
zen-window-sync-migration-dialog-accept = Got It
|
||||
zen-window-sync-migration-dialog-title = Jaga Jendela Anda Tetap Sinkron
|
||||
zen-window-sync-migration-dialog-message = Zen kini menyinkronkan jendela pada perangkat yang sama, sehingga perubahan di satu jendela akan langsung terlihat di jendela lainnya.
|
||||
zen-window-sync-migration-dialog-learn-more = Pelajari Lebih Lanjut
|
||||
zen-window-sync-migration-dialog-accept = Oke!
|
||||
|
||||
@@ -4,19 +4,19 @@
|
||||
|
||||
zen-menubar-toggle-pinned-tabs =
|
||||
.label =
|
||||
{ $pinnedAreCollapsed ->
|
||||
[true] Expand Pinned Tabs
|
||||
*[false] Collapse Pinned Tabs
|
||||
{ $pinnedAreCollapsed ->
|
||||
[true] Perluas Tab yang Disematkan
|
||||
*[false] Ciutkan Tab yang Disematkan
|
||||
}
|
||||
zen-menubar-appearance =
|
||||
.label = Appearance
|
||||
.label = Tampilan
|
||||
zen-menubar-appearance-description =
|
||||
.label = Websites will use:
|
||||
.label = Situs web akan menggunakan:
|
||||
zen-menubar-appearance-auto =
|
||||
.label = Automatic
|
||||
.label = Otomatis
|
||||
zen-menubar-appearance-light =
|
||||
.label = Light
|
||||
.label = Terang
|
||||
zen-menubar-appearance-dark =
|
||||
.label = Dark
|
||||
.label = Gelap
|
||||
zen-menubar-new-unsynced-window =
|
||||
.label = New Blank Window
|
||||
.label = Jendela Kosong Baru
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
|
||||
zen-panel-ui-workspaces-text = Ruang Kerja Lainnya
|
||||
zen-panel-ui-spaces-label =
|
||||
.label = Spaces
|
||||
.label = Ruang
|
||||
zen-panel-ui-workspaces-create =
|
||||
.label = Buat Ruang
|
||||
zen-panel-ui-folder-create =
|
||||
.label = Buat Folder
|
||||
zen-panel-ui-new-empty-split =
|
||||
.label = New Split
|
||||
.label = Split Baru
|
||||
zen-workspaces-panel-context-delete =
|
||||
.label = Hapus Ruang
|
||||
.accesskey = D
|
||||
@@ -66,6 +66,6 @@ zen-workspaces-close-all-unpinned-tabs-title =
|
||||
.label = Bersihkan
|
||||
.tooltiptext = Tutup semua tab yang tidak disematkan
|
||||
zen-panel-ui-workspaces-change-forward =
|
||||
.label = Next Space
|
||||
.label = Ruang Selanjutnya
|
||||
zen-panel-ui-workspaces-change-back =
|
||||
.label = Previous Space
|
||||
.label = Ruang Sebelumnya
|
||||
|
||||
@@ -19,4 +19,4 @@ zen-menubar-appearance-light =
|
||||
zen-menubar-appearance-dark =
|
||||
.label = Dökkt
|
||||
zen-menubar-new-unsynced-window =
|
||||
.label = New Blank Window
|
||||
.label = Nýr auður gluggi
|
||||
|
||||
@@ -19,4 +19,4 @@ zen-menubar-appearance-light =
|
||||
zen-menubar-appearance-dark =
|
||||
.label = 다크
|
||||
zen-menubar-new-unsynced-window =
|
||||
.label = New Blank Window
|
||||
.label = 새 빈 창
|
||||
|
||||
@@ -314,4 +314,4 @@ zen-devtools-toggle-storage-shortcut = Perjungti saugyklą
|
||||
zen-devtools-toggle-dom-shortcut = Perjungti DOM
|
||||
zen-devtools-toggle-accessibility-shortcut = Perjungti prieinamumą
|
||||
zen-close-all-unpinned-tabs-shortcut = Užverti visas neprisegtas korteles
|
||||
zen-new-unsynced-window-shortcut = Naujas nesinchronizuotas langas
|
||||
zen-new-unsynced-window-shortcut = Naujas tuščias langas
|
||||
|
||||
@@ -60,8 +60,8 @@ zen-site-data-settings = Nustatymai
|
||||
zen-generic-manage = Tvarkyti
|
||||
zen-generic-more = Daugiau
|
||||
zen-generic-next = Sekantis
|
||||
zen-essentials-promo-label = Add to Essentials
|
||||
zen-essentials-promo-sublabel = Keep your favorite tabs just a click away
|
||||
zen-essentials-promo-label = Įtraukti į būtiniausius
|
||||
zen-essentials-promo-sublabel = Laikykite mėgstamas korteles vos nuo vienu paspaudimu
|
||||
# These labels will be used for the site data panel settings
|
||||
zen-site-data-setting-allow = Leidžiama
|
||||
zen-site-data-setting-block = Užblokuota
|
||||
@@ -109,7 +109,7 @@ zen-sidebar-notification-updated-tooltip =
|
||||
zen-sidebar-notification-restart-safe-mode-label = Kažkas sugedo?
|
||||
zen-sidebar-notification-restart-safe-mode-tooltip =
|
||||
.title = Paleisti iš naujo saugioje režime
|
||||
zen-window-sync-migration-dialog-title = Keep Your Windows in Sync
|
||||
zen-window-sync-migration-dialog-message = Zen now syncs windows on the same device, so changes in one window are reflected across the others instantly.
|
||||
zen-window-sync-migration-dialog-learn-more = Learn More
|
||||
zen-window-sync-migration-dialog-accept = Got It
|
||||
zen-window-sync-migration-dialog-title = Išlaikykite savo langus sinchronizuotus
|
||||
zen-window-sync-migration-dialog-message = „Zen“ dabar sinchronizuoja langus tame pačiame įrenginyje, todėl viename lange atlikti pakeitimai iš karto atsispindi ir kituose.
|
||||
zen-window-sync-migration-dialog-learn-more = Sužinoti daugiau
|
||||
zen-window-sync-migration-dialog-accept = Supratau
|
||||
|
||||
@@ -19,4 +19,4 @@ zen-menubar-appearance-light =
|
||||
zen-menubar-appearance-dark =
|
||||
.label = Tamsų
|
||||
zen-menubar-new-unsynced-window =
|
||||
.label = New Blank Window
|
||||
.label = Naujas tuščias langas
|
||||
|
||||
@@ -19,4 +19,4 @@ zen-menubar-appearance-light =
|
||||
zen-menubar-appearance-dark =
|
||||
.label = Escuro
|
||||
zen-menubar-new-unsynced-window =
|
||||
.label = New Blank Window
|
||||
.label = Nova janela em branco
|
||||
|
||||
@@ -18,9 +18,9 @@ tab-context-zen-replace-pinned-url-with-current =
|
||||
.label = Substituir o URL Fixado pelo URL Atual
|
||||
.accesskey = C
|
||||
tab-context-zen-edit-title =
|
||||
.label = Change Label...
|
||||
.label = Alterar etiqueta...
|
||||
tab-context-zen-edit-icon =
|
||||
.label = Change Icon...
|
||||
.label = Alterar ícone...
|
||||
zen-themes-corrupted = O seu ficheiro de modificações do { -brand-short-name } está corrompido. Elas foram redefinidas como iguais às do tema padrão.
|
||||
zen-shortcuts-corrupted = O seu ficheiro de atalhos do { -brand-short-name } está corrompido. Eles foram redefinidos para os atalhos padrão.
|
||||
# note: Do not translate the "<br/>" tags in the following string
|
||||
@@ -109,7 +109,7 @@ zen-sidebar-notification-updated-tooltip =
|
||||
zen-sidebar-notification-restart-safe-mode-label = Falhou alguma coisa?
|
||||
zen-sidebar-notification-restart-safe-mode-tooltip =
|
||||
.title = Reiniciar em Modo de Segurança
|
||||
zen-window-sync-migration-dialog-title = Keep Your Windows in Sync
|
||||
zen-window-sync-migration-dialog-message = Zen now syncs windows on the same device, so changes in one window are reflected across the others instantly.
|
||||
zen-window-sync-migration-dialog-title = Mantenha As Suas Janelas Sincronizadas
|
||||
zen-window-sync-migration-dialog-message = Agora, o Zen sincroniza as janelas no dispositivo, pelo que alterações numa janela são refletidas instantaneamente nas outras.
|
||||
zen-window-sync-migration-dialog-learn-more = Learn More
|
||||
zen-window-sync-migration-dialog-accept = Got It
|
||||
zen-window-sync-migration-dialog-accept = Entendido
|
||||
|
||||
@@ -19,4 +19,4 @@ zen-menubar-appearance-light =
|
||||
zen-menubar-appearance-dark =
|
||||
.label = Escuro
|
||||
zen-menubar-new-unsynced-window =
|
||||
.label = New Blank Window
|
||||
.label = Nova janela sem sincronização
|
||||
|
||||
@@ -314,4 +314,4 @@ zen-devtools-toggle-storage-shortcut = Переключить хранилище
|
||||
zen-devtools-toggle-dom-shortcut = Переключить DOM
|
||||
zen-devtools-toggle-accessibility-shortcut = Включить/выключить специальные возможности
|
||||
zen-close-all-unpinned-tabs-shortcut = Закрыть все не закреплённые вкладки
|
||||
zen-new-unsynced-window-shortcut = Новое несинхронизированное окно
|
||||
zen-new-unsynced-window-shortcut = Новое пустое окно
|
||||
|
||||
@@ -314,4 +314,4 @@ zen-devtools-toggle-storage-shortcut = Växla lagring
|
||||
zen-devtools-toggle-dom-shortcut = Växla DOM
|
||||
zen-devtools-toggle-accessibility-shortcut = Växla tillgänglighetsinställningar
|
||||
zen-close-all-unpinned-tabs-shortcut = Stäng alla flikar som inte är fästa
|
||||
zen-new-unsynced-window-shortcut = Nytt osynkroniserat fönster
|
||||
zen-new-unsynced-window-shortcut = Nytt tomt fönster
|
||||
|
||||
@@ -19,4 +19,4 @@ zen-menubar-appearance-light =
|
||||
zen-menubar-appearance-dark =
|
||||
.label = Mörkt
|
||||
zen-menubar-new-unsynced-window =
|
||||
.label = New Blank Window
|
||||
.label = Nytt tomt fönster
|
||||
|
||||
@@ -314,4 +314,4 @@ zen-devtools-toggle-storage-shortcut = Depolamayı Aç/Kapat
|
||||
zen-devtools-toggle-dom-shortcut = DOM'u Aç/Kapat
|
||||
zen-devtools-toggle-accessibility-shortcut = Erişilebilirliği Aç/Kapat
|
||||
zen-close-all-unpinned-tabs-shortcut = Sabitlenmemiş Tüm Sekmeleri Kapat
|
||||
zen-new-unsynced-window-shortcut = Senkronize Edilmemiş Yeni Pencere
|
||||
zen-new-unsynced-window-shortcut = Yeni Boş Pencere
|
||||
|
||||
@@ -19,4 +19,4 @@ zen-menubar-appearance-light =
|
||||
zen-menubar-appearance-dark =
|
||||
.label = Koyu
|
||||
zen-menubar-new-unsynced-window =
|
||||
.label = New Blank Window
|
||||
.label = Yeni Boş Pencere
|
||||
|
||||
@@ -314,4 +314,4 @@ zen-devtools-toggle-storage-shortcut = 開啟儲存空間檢測器
|
||||
zen-devtools-toggle-dom-shortcut = 開啟 DOM
|
||||
zen-devtools-toggle-accessibility-shortcut = 開啟輔助功能
|
||||
zen-close-all-unpinned-tabs-shortcut = 關閉所有未釘選的分頁
|
||||
zen-new-unsynced-window-shortcut = 開新未同步視窗
|
||||
zen-new-unsynced-window-shortcut = 開新初始視窗
|
||||
|
||||
@@ -19,4 +19,4 @@ zen-menubar-appearance-light =
|
||||
zen-menubar-appearance-dark =
|
||||
.label = 暗色
|
||||
zen-menubar-new-unsynced-window =
|
||||
.label = 新的初始視窗
|
||||
.label = 開新初始視窗
|
||||
|
||||
@@ -49,7 +49,7 @@ zen-panel-ui-gradient-click-to-add = 點擊新增顏色
|
||||
zen-workspace-creation-name =
|
||||
.placeholder = 工作區名稱
|
||||
zen-move-tab-to-workspace-button =
|
||||
.label = 移動至……
|
||||
.label = 移動至…
|
||||
.tooltiptext = 將此視窗所有頁面移至單一工作區
|
||||
zen-workspaces-panel-context-reorder =
|
||||
.label = 排序工作區
|
||||
|
||||
6
package-lock.json
generated
6
package-lock.json
generated
@@ -5610,9 +5610,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"version": "4.17.23",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
|
||||
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
|
||||
@@ -54,3 +54,6 @@
|
||||
|
||||
- name: zen.view.draggable-sidebar
|
||||
value: true
|
||||
|
||||
- name: zen.view.overflow-webext-toolbar
|
||||
value: true
|
||||
|
||||
@@ -13,3 +13,6 @@
|
||||
|
||||
- name: zen.window-sync.open-link-in-new-unsynced-window
|
||||
value: true
|
||||
|
||||
- name: zen.window-sync.sync-only-pinned-tabs
|
||||
value: false
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
- name: zen.urlbar.show-pip-button
|
||||
value: false
|
||||
|
||||
- name: zen.urlbar.open-on-startup
|
||||
value: true
|
||||
|
||||
# Mark: Zen suggestions controls
|
||||
|
||||
- name: zen.urlbar.suggestions.quick-actions
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import requests
|
||||
|
||||
BASE_URI = "https://phabricator.services.mozilla.com"
|
||||
OUTPUT_DIR = os.path.join(os.getcwd(), "src", "firefox-patches")
|
||||
|
||||
|
||||
def download_phab_patch(phab_id, output_file):
|
||||
"""Download a Phabricator patch by its ID and save it to output_file."""
|
||||
patch_url = f"{BASE_URI}/{phab_id}?download=true"
|
||||
try:
|
||||
print(f"Downloading patch from {patch_url}")
|
||||
response = requests.get(patch_url)
|
||||
response.raise_for_status() # Raise an error for bad responses
|
||||
with open(output_file, 'wb') as f:
|
||||
f.write(response.content)
|
||||
print(f"Patch saved to {output_file}")
|
||||
except requests.RequestException as e:
|
||||
print(f"Error downloading patch: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python download_phab_patch.py <PHABRICATOR_ID> [output_file]", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
phab_id = sys.argv[1]
|
||||
output_file = sys.argv[2] if len(sys.argv) > 2 else f"phab_{phab_id}"
|
||||
output_file = os.path.join(OUTPUT_DIR, output_file + ".patch")
|
||||
|
||||
download_phab_patch(phab_id, output_file)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -18,10 +18,18 @@ FILE_PREFIX = """
|
||||
# This file is autogenerated by scripts/import_external_tests.py
|
||||
# Do not edit manually.
|
||||
|
||||
"""
|
||||
|
||||
BROWSER_MANIFEST_LIST_PREFIX = """
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
"""
|
||||
|
||||
XPCSHELL_MANIFESTS_LIST_PREFIX = """
|
||||
XPCSHELL_TESTS_MANIFESTS += [
|
||||
"""
|
||||
|
||||
FILE_SUFFIX = "]"
|
||||
VALID_MANIFEST_FILES = ["browser.toml", "xpcshell.toml"]
|
||||
|
||||
|
||||
def get_tests_manifest():
|
||||
@@ -38,12 +46,17 @@ def validate_tests_path(path, files, ignore_list):
|
||||
for ignore in ignore_list:
|
||||
if ignore not in files:
|
||||
die_with_error(f"Ignore file '{ignore}' not found in tests folder '{path}'")
|
||||
if "browser.toml" not in files or "browser.js" in ignore_list:
|
||||
die_with_error(f"'browser.toml' not found in tests folder '{path}'")
|
||||
if not any(manifest_file in files for manifest_file in VALID_MANIFEST_FILES):
|
||||
die_with_error(f"None of the valid manifest files {VALID_MANIFEST_FILES} found in tests folder '{path}'")
|
||||
|
||||
|
||||
def disable_and_replace_manifest(manifest, output_path):
|
||||
toml_file = os.path.join(output_path, "browser.toml")
|
||||
toml_file = None
|
||||
for manifest_file in VALID_MANIFEST_FILES:
|
||||
candidate = os.path.join(output_path, manifest_file)
|
||||
if os.path.exists(candidate):
|
||||
toml_file = candidate
|
||||
break
|
||||
disabled_tests = manifest.get("disable", [])
|
||||
with open(toml_file, "r") as f:
|
||||
data = f.read()
|
||||
@@ -90,8 +103,17 @@ def write_moz_build_file(manifest):
|
||||
print(f"Writing moz.build file to '{moz_build_path}'")
|
||||
with open(moz_build_path, "w") as f:
|
||||
f.write(FILE_PREFIX)
|
||||
f.write(BROWSER_MANIFEST_LIST_PREFIX)
|
||||
for test_suite in manifest.keys():
|
||||
f.write(f'\t"{test_suite}/browser.toml",\n')
|
||||
# add for browser.toml first
|
||||
if not manifest[test_suite].get("xpcshell", False):
|
||||
f.write(f'\t"{test_suite}/browser.toml",\n')
|
||||
f.write(FILE_SUFFIX)
|
||||
f.write(XPCSHELL_MANIFESTS_LIST_PREFIX)
|
||||
for test_suite in manifest.keys():
|
||||
# add for xpcshell.toml
|
||||
if manifest[test_suite].get("xpcshell", False):
|
||||
f.write(f'\t"{test_suite}/xpcshell.toml",\n')
|
||||
f.write(FILE_SUFFIX)
|
||||
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ def main():
|
||||
os.chdir(engine_dir)
|
||||
|
||||
def run_mach_with_paths(test_paths):
|
||||
command = ['./mach', 'mochitest'] + other_args + test_paths
|
||||
command = ['./mach', 'test'] + other_args + test_paths
|
||||
# Replace the current process with the mach command
|
||||
os.execvp(command[0], command)
|
||||
|
||||
|
||||
99
scripts/update_external_patches.py
Normal file
99
scripts/update_external_patches.py
Normal file
@@ -0,0 +1,99 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import requests
|
||||
from json_with_comments import JSONWithCommentsDecoder
|
||||
|
||||
BASE_URI = "https://phabricator.services.mozilla.com"
|
||||
OUTPUT_DIR = os.path.join(os.getcwd(), "src", "external-patches")
|
||||
|
||||
|
||||
def die(message):
|
||||
print(f"Error: {message}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def download_phab_patch(phab_id, output_file):
|
||||
"""Download a Phabricator patch by its ID and save it to output_file."""
|
||||
patch_url = f"{BASE_URI}/{phab_id}?download=true"
|
||||
try:
|
||||
print(f"Downloading patch from {patch_url}")
|
||||
response = requests.get(patch_url)
|
||||
response.raise_for_status() # Raise an error for bad responses
|
||||
with open(output_file, 'wb') as f:
|
||||
f.write(response.content)
|
||||
print(f"Patch saved to {output_file}")
|
||||
except requests.RequestException as e:
|
||||
die(f"Failed to download patch {phab_id}: {e}")
|
||||
|
||||
|
||||
def download_patch_from_url(url, output_file):
|
||||
"""Download a patch from a given URL and save it to output_file."""
|
||||
try:
|
||||
print(f"Downloading patch from {url}")
|
||||
response = requests.get(url)
|
||||
response.raise_for_status() # Raise an error for bad responses
|
||||
with open(output_file, 'wb') as f:
|
||||
f.write(response.content)
|
||||
print(f"Patch saved to {output_file}")
|
||||
except requests.RequestException as e:
|
||||
die(f"Failed to download patch from {url}: {e}")
|
||||
|
||||
|
||||
def main():
|
||||
with open(os.path.join(OUTPUT_DIR, "manifest.json"), 'r') as f:
|
||||
manifest = json.load(f, cls=JSONWithCommentsDecoder)
|
||||
|
||||
expected_files = set()
|
||||
for patch in manifest:
|
||||
if patch.get("type") == "phabricator":
|
||||
phab_id = patch.get("id")
|
||||
name = patch.get("name")
|
||||
if not phab_id or not name:
|
||||
die(f"Patch entry missing 'id' or 'name': {patch}")
|
||||
name = name.replace(" ", "_").lower()
|
||||
output_file = os.path.join(OUTPUT_DIR, "firefox", f"{name}.patch")
|
||||
print(f"Processing Phabricator patch: {phab_id} -> {output_file}")
|
||||
download_phab_patch(phab_id, output_file)
|
||||
expected_files.add(output_file)
|
||||
elif patch.get("type") == "local":
|
||||
print(f"Local patch: {patch.get('path')}")
|
||||
expected_files.add(os.path.join(OUTPUT_DIR, patch.get("path")))
|
||||
elif patch.get("type") == "patch":
|
||||
url = patch.get("url")
|
||||
dest = patch.get("dest")
|
||||
if not url or not dest:
|
||||
die(f"Patch entry missing 'url' or 'dest': {patch}")
|
||||
filename = url.split("/")[-1]
|
||||
output_file = os.path.join(OUTPUT_DIR, dest, filename)
|
||||
download_patch_from_url(url, output_file)
|
||||
replaces = patch.get("replaces", {})
|
||||
for replace in replaces.keys():
|
||||
value = replaces[replace]
|
||||
with open(output_file, 'r') as f:
|
||||
content = f.read()
|
||||
if replace not in content:
|
||||
die(f"Replace string '{replace}' not found in {output_file}")
|
||||
with open(output_file, 'w') as f:
|
||||
f.write(content.replace(replace, value))
|
||||
expected_files.add(output_file)
|
||||
else:
|
||||
die(f"Unknown patch type: {patch.get('type')}")
|
||||
|
||||
# Check for unexpected files in the output directory
|
||||
# and remove them if they are not in the expected_files set.
|
||||
for root, dirs, files in os.walk(OUTPUT_DIR):
|
||||
for file in files:
|
||||
if file.endswith(".patch"):
|
||||
file_path = os.path.join(root, file)
|
||||
if file_path not in expected_files:
|
||||
print(f"Removing unexpected patch file: {file_path}")
|
||||
os.remove(file_path)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/base/content/navigator-toolbox.inc.xhtml b/browser/base/content/navigator-toolbox.inc.xhtml
|
||||
index 68c24f730d56f548cf1e286198a04f8363529378..71418c93ce7216d71412f2fa67295322bb73abad 100644
|
||||
index 68c24f730d56f548cf1e286198a04f8363529378..eb9aa5e77cf549062d8d3770f8057ceafe67c317 100644
|
||||
--- a/browser/base/content/navigator-toolbox.inc.xhtml
|
||||
+++ b/browser/base/content/navigator-toolbox.inc.xhtml
|
||||
@@ -2,7 +2,7 @@
|
||||
@@ -22,16 +22,17 @@ index 68c24f730d56f548cf1e286198a04f8363529378..71418c93ce7216d71412f2fa67295322
|
||||
<toolbar id="TabsToolbar"
|
||||
class="browser-toolbar browser-titlebar"
|
||||
fullscreentoolbar="true"
|
||||
@@ -62,6 +61,8 @@
|
||||
@@ -62,6 +61,9 @@
|
||||
<html:sidebar-pins-promo id="drag-to-pin-promo-card"></html:sidebar-pins-promo>
|
||||
<arrowscrollbox id="pinned-tabs-container" orient="horizontal" clicktoscroll=""></arrowscrollbox>
|
||||
<splitter orient="vertical" id="vertical-pinned-tabs-splitter" resizebefore="sibling" resizeafter="none" hidden="true"/>
|
||||
+<html:div id="zen-overflow-extensions-list" skipintoolbarset="true"></html:div>
|
||||
+<html:div id="zen-essentials" skipintoolbarset="true"></html:div>
|
||||
+<html:div id="zen-tabs-wrapper">
|
||||
<hbox class="tab-drop-indicator" hidden="true"/>
|
||||
<arrowscrollbox id="tabbrowser-arrowscrollbox" orient="horizontal" flex="1" clicktoscroll="" scrolledtostart="" scrolledtoend="">
|
||||
<tab is="tabbrowser-tab" class="tabbrowser-tab" selected="true" visuallyselected="" fadein=""/>
|
||||
@@ -81,6 +82,7 @@
|
||||
@@ -81,6 +83,7 @@
|
||||
tooltip="dynamic-shortcut-tooltip"
|
||||
data-l10n-id="tabs-toolbar-new-tab"/>
|
||||
<html:span id="tabbrowser-tab-a11y-desc" hidden="true"/>
|
||||
@@ -39,7 +40,7 @@ index 68c24f730d56f548cf1e286198a04f8363529378..71418c93ce7216d71412f2fa67295322
|
||||
</tabs>
|
||||
|
||||
<toolbarbutton id="new-tab-button"
|
||||
@@ -106,9 +108,10 @@
|
||||
@@ -106,9 +109,10 @@
|
||||
#include private-browsing-indicator.inc.xhtml
|
||||
<toolbarbutton class="content-analysis-indicator toolbarbutton-1 content-analysis-indicator-icon"/>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/customizableui/CustomizableUI.sys.mjs b/browser/components/customizableui/CustomizableUI.sys.mjs
|
||||
index 9a98f56d83ee38e0f1aa41467b4ddf215c3d90f7..39e947ce083ce3b293337f5dbb40cd0b46db12e2 100644
|
||||
index 9a98f56d83ee38e0f1aa41467b4ddf215c3d90f7..c50781a1e8fd1a71baf497ba64d85292fa1347f4 100644
|
||||
--- a/browser/components/customizableui/CustomizableUI.sys.mjs
|
||||
+++ b/browser/components/customizableui/CustomizableUI.sys.mjs
|
||||
@@ -14,6 +14,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
@@ -153,7 +153,17 @@ index 9a98f56d83ee38e0f1aa41467b4ddf215c3d90f7..39e947ce083ce3b293337f5dbb40cd0b
|
||||
/**
|
||||
* Add a widget to an area.
|
||||
* If the area to which you try to add is not known to CustomizableUI,
|
||||
@@ -7858,7 +7858,7 @@ class OverflowableToolbar {
|
||||
@@ -7798,7 +7798,9 @@ class OverflowableToolbar {
|
||||
);
|
||||
|
||||
if (webExtList && CustomizableUI.isWebExtensionWidget(child.id)) {
|
||||
+ if (webExtList.id !== "zen-overflow-extensions-list") {
|
||||
child.setAttribute("cui-anchorid", webExtButtonID);
|
||||
+ }
|
||||
webExtList.insertBefore(child, webExtList.firstElementChild);
|
||||
} else {
|
||||
child.setAttribute("cui-anchorid", this.#defaultListButton.id);
|
||||
@@ -7858,7 +7860,7 @@ class OverflowableToolbar {
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
@@ -162,7 +172,7 @@ index 9a98f56d83ee38e0f1aa41467b4ddf215c3d90f7..39e947ce083ce3b293337f5dbb40cd0b
|
||||
if (child != aExceptChild) {
|
||||
sum += getInlineSize(child);
|
||||
}
|
||||
@@ -7882,11 +7882,11 @@ class OverflowableToolbar {
|
||||
@@ -7882,11 +7884,11 @@ class OverflowableToolbar {
|
||||
parseFloat(style.paddingLeft) -
|
||||
parseFloat(style.paddingRight) -
|
||||
toolbarChildrenWidth;
|
||||
@@ -176,7 +186,7 @@ index 9a98f56d83ee38e0f1aa41467b4ddf215c3d90f7..39e947ce083ce3b293337f5dbb40cd0b
|
||||
});
|
||||
|
||||
lazy.log.debug(
|
||||
@@ -7901,7 +7901,14 @@ class OverflowableToolbar {
|
||||
@@ -7901,7 +7903,14 @@ class OverflowableToolbar {
|
||||
Math.max(targetWidth, targetChildrenWidth)
|
||||
);
|
||||
totalAvailWidth = Math.ceil(totalAvailWidth);
|
||||
@@ -192,7 +202,7 @@ index 9a98f56d83ee38e0f1aa41467b4ddf215c3d90f7..39e947ce083ce3b293337f5dbb40cd0b
|
||||
return { isOverflowing, targetContentWidth, totalAvailWidth };
|
||||
}
|
||||
|
||||
@@ -7962,7 +7969,11 @@ class OverflowableToolbar {
|
||||
@@ -7962,7 +7971,11 @@ class OverflowableToolbar {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -205,7 +215,7 @@ index 9a98f56d83ee38e0f1aa41467b4ddf215c3d90f7..39e947ce083ce3b293337f5dbb40cd0b
|
||||
lazy.log.debug(
|
||||
`Need ${minSize} but width is ${totalAvailWidth} so bailing`
|
||||
);
|
||||
@@ -7995,7 +8006,7 @@ class OverflowableToolbar {
|
||||
@@ -7995,7 +8008,7 @@ class OverflowableToolbar {
|
||||
}
|
||||
}
|
||||
if (!inserted) {
|
||||
@@ -214,7 +224,27 @@ index 9a98f56d83ee38e0f1aa41467b4ddf215c3d90f7..39e947ce083ce3b293337f5dbb40cd0b
|
||||
}
|
||||
child.removeAttribute("cui-anchorid");
|
||||
child.removeAttribute("overflowedItem");
|
||||
@@ -8340,7 +8351,7 @@ class OverflowableToolbar {
|
||||
@@ -8121,6 +8134,9 @@ class OverflowableToolbar {
|
||||
* if no such list exists.
|
||||
*/
|
||||
get #webExtList() {
|
||||
+ if (this.#toolbar.getAttribute("addon-webext-overflowtarget") !== this.#webExtListRef?.id) {
|
||||
+ this.#webExtListRef = null;
|
||||
+ }
|
||||
if (!this.#webExtListRef) {
|
||||
let targetID = this.#toolbar.getAttribute("addon-webext-overflowtarget");
|
||||
if (!targetID) {
|
||||
@@ -8132,6 +8148,9 @@ class OverflowableToolbar {
|
||||
let win = this.#toolbar.ownerGlobal;
|
||||
let { panel } = win.gUnifiedExtensions;
|
||||
this.#webExtListRef = panel.querySelector(`#${targetID}`);
|
||||
+ if (!this.#webExtListRef) {
|
||||
+ this.#webExtListRef = win.document.getElementById(targetID);
|
||||
+ }
|
||||
}
|
||||
return this.#webExtListRef;
|
||||
}
|
||||
@@ -8340,7 +8359,7 @@ class OverflowableToolbar {
|
||||
break;
|
||||
}
|
||||
case "mousedown": {
|
||||
|
||||
@@ -736,6 +736,7 @@ var gZenWorkspacesSettings = {
|
||||
Services.prefs.addObserver("zen.glance.enabled", tabsUnloaderPrefListener); // We can use the same listener for both prefs
|
||||
Services.prefs.addObserver("zen.workspaces.separate-essentials", tabsUnloaderPrefListener);
|
||||
Services.prefs.addObserver("zen.glance.activation-method", tabsUnloaderPrefListener);
|
||||
Services.prefs.addObserver("zen.window-sync.sync-only-pinned-tabs", tabsUnloaderPrefListener);
|
||||
Services.prefs.addObserver(
|
||||
"zen.tabs.ctrl-tab.ignore-essential-tabs",
|
||||
toggleZenCycleByAttrWarning
|
||||
@@ -745,6 +746,10 @@ var gZenWorkspacesSettings = {
|
||||
Services.prefs.removeObserver("zen.glance.enabled", tabsUnloaderPrefListener);
|
||||
Services.prefs.removeObserver("zen.glance.activation-method", tabsUnloaderPrefListener);
|
||||
Services.prefs.removeObserver("zen.workspaces.separate-essentials", tabsUnloaderPrefListener);
|
||||
Services.prefs.removeObserver(
|
||||
"zen.window-sync.sync-only-pinned-tabs",
|
||||
tabsUnloaderPrefListener
|
||||
);
|
||||
Services.prefs.removeObserver(
|
||||
"zen.tabs.ctrl-tab.ignore-essential-tabs",
|
||||
toggleZenCycleByAttrWarning
|
||||
@@ -1198,6 +1203,11 @@ Preferences.addAll([
|
||||
type: "bool",
|
||||
default: true,
|
||||
},
|
||||
{
|
||||
id: "zen.window-sync.sync-only-pinned-tabs",
|
||||
type: "bool",
|
||||
default: false,
|
||||
},
|
||||
]);
|
||||
|
||||
Preferences.addSetting({
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
<label><html:h2 data-l10n-id="zen-settings-workspaces-header"/></label>
|
||||
<description class="description-deemphasized" data-l10n-id="zen-settings-workspaces-description" />
|
||||
|
||||
<checkbox id="zenWorkspacesSyncUnpinnedTabs"
|
||||
data-l10n-id="zen-settings-workspaces-sync-unpinned-tabs"
|
||||
preference="zen.window-sync.sync-only-pinned-tabs"/>
|
||||
<checkbox id="zenWorkspacesHideDefaultContainer"
|
||||
data-l10n-id="zen-settings-workspaces-hide-default-container-indicator"
|
||||
preference="zen.workspaces.hide-default-container-indicator"/>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/sessionstore/SessionStartup.sys.mjs b/browser/components/sessionstore/SessionStartup.sys.mjs
|
||||
index 86600ffb5178599ab23270a964064ca657a3283f..e7014e5bce547d37ec92377a95bad5be4d52152e 100644
|
||||
index 86600ffb5178599ab23270a964064ca657a3283f..97975af7822a157eafe02ec8bbebdf1a6b564ccb 100644
|
||||
--- a/browser/components/sessionstore/SessionStartup.sys.mjs
|
||||
+++ b/browser/components/sessionstore/SessionStartup.sys.mjs
|
||||
@@ -40,6 +40,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
@@ -28,7 +28,16 @@ index 86600ffb5178599ab23270a964064ca657a3283f..e7014e5bce547d37ec92377a95bad5be
|
||||
if (this._initialState == null) {
|
||||
// No valid session found.
|
||||
this._sessionType = this.NO_SESSION;
|
||||
@@ -336,12 +339,7 @@ export var SessionStartup = {
|
||||
@@ -276,6 +279,8 @@ export var SessionStartup = {
|
||||
`Previous shutdown ok? ${this._previousSessionCrashed}, reason: ${previousSessionCrashedReason}`
|
||||
);
|
||||
|
||||
+ lazy.ZenSessionStore.onCrashCheckpoints(this._initialState);
|
||||
+
|
||||
Services.obs.addObserver(this, "sessionstore-windows-restored", true);
|
||||
|
||||
if (this.sessionType == this.NO_SESSION) {
|
||||
@@ -336,12 +341,7 @@ export var SessionStartup = {
|
||||
isAutomaticRestoreEnabled() {
|
||||
if (this._resumeSessionEnabled === null) {
|
||||
this._resumeSessionEnabled =
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/sessionstore/SessionStore.sys.mjs b/browser/components/sessionstore/SessionStore.sys.mjs
|
||||
index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96faedf6f0b 100644
|
||||
index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2061ef7ac60371a563b4e4cd77ceab586f767a5e 100644
|
||||
--- a/browser/components/sessionstore/SessionStore.sys.mjs
|
||||
+++ b/browser/components/sessionstore/SessionStore.sys.mjs
|
||||
@@ -127,6 +127,9 @@ const TAB_EVENTS = [
|
||||
@@ -79,7 +79,15 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
!lazy.SessionStartup.willRestore()
|
||||
) {
|
||||
// We want to split the window up into pinned tabs and unpinned tabs.
|
||||
@@ -2239,6 +2248,15 @@ var SessionStoreInternal = {
|
||||
@@ -2211,6 +2220,7 @@ var SessionStoreInternal = {
|
||||
}
|
||||
|
||||
if (newWindowState) {
|
||||
+ lazy.ZenSessionStore.onRestoringClosedWindow(newWindowState);
|
||||
// Ensure that the window state isn't hidden
|
||||
this._restoreCount = 1;
|
||||
let state = { windows: [newWindowState] };
|
||||
@@ -2239,6 +2249,15 @@ var SessionStoreInternal = {
|
||||
});
|
||||
this._shouldRestoreLastSession = false;
|
||||
}
|
||||
@@ -95,7 +103,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
|
||||
if (this._restoreLastWindow && aWindow.toolbar.visible) {
|
||||
// always reset (if not a popup window)
|
||||
@@ -2383,7 +2401,7 @@ var SessionStoreInternal = {
|
||||
@@ -2383,7 +2402,7 @@ var SessionStoreInternal = {
|
||||
|
||||
var tabbrowser = aWindow.gBrowser;
|
||||
|
||||
@@ -104,7 +112,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
|
||||
TAB_EVENTS.forEach(function (aEvent) {
|
||||
tabbrowser.tabContainer.removeEventListener(aEvent, this, true);
|
||||
@@ -2434,7 +2452,7 @@ var SessionStoreInternal = {
|
||||
@@ -2434,7 +2453,7 @@ var SessionStoreInternal = {
|
||||
|
||||
let isLastRegularWindow =
|
||||
Object.values(this._windows).filter(
|
||||
@@ -113,7 +121,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
).length == 1;
|
||||
this._log.debug(
|
||||
`onClose, closing window isLastRegularWindow? ${isLastRegularWindow}`
|
||||
@@ -2491,8 +2509,8 @@ var SessionStoreInternal = {
|
||||
@@ -2491,8 +2510,8 @@ var SessionStoreInternal = {
|
||||
// 2) Flush the window.
|
||||
// 3) When the flush is complete, revisit our decision to store the window
|
||||
// in _closedWindows, and add/remove as necessary.
|
||||
@@ -124,7 +132,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
}
|
||||
|
||||
completionPromise = lazy.TabStateFlusher.flushWindow(aWindow).then(() => {
|
||||
@@ -2512,8 +2530,9 @@ var SessionStoreInternal = {
|
||||
@@ -2512,8 +2531,9 @@ var SessionStoreInternal = {
|
||||
|
||||
// Save non-private windows if they have at
|
||||
// least one saveable tab or are the last window.
|
||||
@@ -136,7 +144,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
|
||||
if (!isLastWindow && winData.closedId > -1) {
|
||||
this._addClosedAction(
|
||||
@@ -2589,7 +2608,7 @@ var SessionStoreInternal = {
|
||||
@@ -2589,7 +2609,7 @@ var SessionStoreInternal = {
|
||||
* to call this method again asynchronously (for example, after
|
||||
* a window flush).
|
||||
*/
|
||||
@@ -145,7 +153,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
// Make sure SessionStore is still running, and make sure that we
|
||||
// haven't chosen to forget this window.
|
||||
if (
|
||||
@@ -2606,6 +2625,7 @@ var SessionStoreInternal = {
|
||||
@@ -2606,6 +2626,7 @@ var SessionStoreInternal = {
|
||||
// _closedWindows from a previous call to this function.
|
||||
let winIndex = this._closedWindows.indexOf(winData);
|
||||
let alreadyStored = winIndex != -1;
|
||||
@@ -153,7 +161,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
// If sidebar command is truthy, i.e. sidebar is open, store sidebar settings
|
||||
let shouldStore = hasSaveableTabs || isLastWindow;
|
||||
|
||||
@@ -3408,7 +3428,7 @@ var SessionStoreInternal = {
|
||||
@@ -3408,7 +3429,7 @@ var SessionStoreInternal = {
|
||||
if (!isPrivateWindow && tabState.isPrivate) {
|
||||
return;
|
||||
}
|
||||
@@ -162,7 +170,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4129,6 +4149,12 @@ var SessionStoreInternal = {
|
||||
@@ -4129,6 +4150,12 @@ var SessionStoreInternal = {
|
||||
Math.min(tabState.index, tabState.entries.length)
|
||||
);
|
||||
tabState.pinned = false;
|
||||
@@ -175,7 +183,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
|
||||
if (inBackground === false) {
|
||||
aWindow.gBrowser.selectedTab = newTab;
|
||||
@@ -4565,6 +4591,8 @@ var SessionStoreInternal = {
|
||||
@@ -4565,6 +4592,8 @@ var SessionStoreInternal = {
|
||||
// Append the tab if we're opening into a different window,
|
||||
tabIndex: aSource == aTargetWindow ? pos : Infinity,
|
||||
pinned: state.pinned,
|
||||
@@ -184,7 +192,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
userContextId: state.userContextId,
|
||||
skipLoad: true,
|
||||
preferredRemoteType,
|
||||
@@ -5414,7 +5442,7 @@ var SessionStoreInternal = {
|
||||
@@ -5414,7 +5443,7 @@ var SessionStoreInternal = {
|
||||
|
||||
for (let i = tabbrowser.pinnedTabCount; i < tabbrowser.tabs.length; i++) {
|
||||
let tab = tabbrowser.tabs[i];
|
||||
@@ -193,7 +201,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
removableTabs.push(tab);
|
||||
}
|
||||
}
|
||||
@@ -5525,7 +5553,7 @@ var SessionStoreInternal = {
|
||||
@@ -5525,7 +5554,7 @@ var SessionStoreInternal = {
|
||||
|
||||
// collect the data for all windows
|
||||
for (ix in this._windows) {
|
||||
@@ -202,7 +210,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
// window data is still in _statesToRestore
|
||||
continue;
|
||||
}
|
||||
@@ -5668,11 +5696,12 @@ var SessionStoreInternal = {
|
||||
@@ -5668,11 +5697,12 @@ var SessionStoreInternal = {
|
||||
}
|
||||
|
||||
let tabbrowser = aWindow.gBrowser;
|
||||
@@ -216,7 +224,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
// update the internal state data for this window
|
||||
for (let tab of tabs) {
|
||||
if (tab == aWindow.FirefoxViewHandler.tab) {
|
||||
@@ -5683,6 +5712,9 @@ var SessionStoreInternal = {
|
||||
@@ -5683,6 +5713,9 @@ var SessionStoreInternal = {
|
||||
tabsData.push(tabData);
|
||||
}
|
||||
|
||||
@@ -226,7 +234,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
// update tab group state for this window
|
||||
winData.groups = [];
|
||||
for (let tabGroup of aWindow.gBrowser.tabGroups) {
|
||||
@@ -5695,7 +5727,7 @@ var SessionStoreInternal = {
|
||||
@@ -5695,7 +5728,7 @@ var SessionStoreInternal = {
|
||||
// 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) {
|
||||
@@ -235,7 +243,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
winData.title = tabbrowser.tabs[0].label;
|
||||
}
|
||||
winData.selected = selectedIndex;
|
||||
@@ -5810,8 +5842,8 @@ var SessionStoreInternal = {
|
||||
@@ -5810,8 +5843,8 @@ var SessionStoreInternal = {
|
||||
// selectTab represents.
|
||||
let selectTab = 0;
|
||||
if (overwriteTabs) {
|
||||
@@ -246,7 +254,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
selectTab = Math.min(selectTab, winData.tabs.length);
|
||||
}
|
||||
|
||||
@@ -5833,6 +5865,7 @@ var SessionStoreInternal = {
|
||||
@@ -5833,6 +5866,7 @@ var SessionStoreInternal = {
|
||||
if (overwriteTabs) {
|
||||
for (let i = tabbrowser.browsers.length - 1; i >= 0; i--) {
|
||||
if (!tabbrowser.tabs[i].selected) {
|
||||
@@ -254,7 +262,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
tabbrowser.removeTab(tabbrowser.tabs[i]);
|
||||
}
|
||||
}
|
||||
@@ -5866,6 +5899,12 @@ var SessionStoreInternal = {
|
||||
@@ -5866,6 +5900,12 @@ var SessionStoreInternal = {
|
||||
savedTabGroup => !openTabGroupIdsInWindow.has(savedTabGroup.id)
|
||||
);
|
||||
}
|
||||
@@ -267,7 +275,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
|
||||
// Move the originally open tabs to the end.
|
||||
if (initialTabs) {
|
||||
@@ -6419,6 +6458,25 @@ var SessionStoreInternal = {
|
||||
@@ -6419,6 +6459,25 @@ var SessionStoreInternal = {
|
||||
|
||||
// Most of tabData has been restored, now continue with restoring
|
||||
// attributes that may trigger external events.
|
||||
@@ -293,7 +301,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
|
||||
if (tabData.pinned) {
|
||||
tabbrowser.pinTab(tab);
|
||||
@@ -6567,6 +6625,9 @@ var SessionStoreInternal = {
|
||||
@@ -6567,6 +6626,9 @@ var SessionStoreInternal = {
|
||||
aWindow.gURLBar.readOnly = false;
|
||||
}
|
||||
}
|
||||
@@ -303,7 +311,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
|
||||
let promiseParts = Promise.withResolvers();
|
||||
aWindow.setTimeout(() => {
|
||||
@@ -7343,7 +7404,7 @@ var SessionStoreInternal = {
|
||||
@@ -7343,7 +7405,7 @@ var SessionStoreInternal = {
|
||||
|
||||
let groupsToSave = new Map();
|
||||
for (let tIndex = 0; tIndex < window.tabs.length; ) {
|
||||
@@ -312,7 +320,7 @@ index 2a055f0c5f34f0a2667f659185120c07d38f4e41..2f63071f78782dbc30bde25b3bcaa96f
|
||||
// Adjust window.selected
|
||||
if (tIndex + 1 < window.selected) {
|
||||
window.selected -= 1;
|
||||
@@ -7358,7 +7419,7 @@ var SessionStoreInternal = {
|
||||
@@ -7358,7 +7420,7 @@ var SessionStoreInternal = {
|
||||
);
|
||||
// We don't want to increment tIndex here.
|
||||
continue;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/tabbrowser/content/drag-and-drop.js b/browser/components/tabbrowser/content/drag-and-drop.js
|
||||
index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b1f2bf82b 100644
|
||||
index 57800333445ec7850742145527e04ae8d504b0bb..a13875436a72f89178455a09c8665b9a1ef240b5 100644
|
||||
--- a/browser/components/tabbrowser/content/drag-and-drop.js
|
||||
+++ b/browser/components/tabbrowser/content/drag-and-drop.js
|
||||
@@ -35,6 +35,9 @@
|
||||
@@ -39,7 +39,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
|
||||
event.stopPropagation();
|
||||
+ if (draggedTab && dropEffect == "move") {
|
||||
+ this.handle_drop_transition?.(draggedTab._dragData.dropElement, draggedTab, movingTabs, draggedTab._dragData.dropBefore);
|
||||
+ gZenPinnedTabManager.moveToAnotherTabContainerIfNecessary(event, movingTabs);
|
||||
+ gZenPinnedTabManager.moveToAnotherTabContainerIfNecessary(event, draggedTab, movingTabs, this._getDropIndex(event));
|
||||
+ }
|
||||
if (draggedTab && dropEffect == "copy") {
|
||||
let duplicatedDraggedTab;
|
||||
@@ -102,7 +102,36 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
|
||||
postTransitionCleanup();
|
||||
} else {
|
||||
let onTransitionEnd = transitionendEvent => {
|
||||
@@ -584,6 +597,7 @@
|
||||
@@ -513,7 +526,7 @@
|
||||
if (tab.selected) {
|
||||
selectedTab = tab;
|
||||
indexForSelectedTab = newIndex;
|
||||
- } else {
|
||||
+ } else if (false) {
|
||||
const newTab = gBrowser.adoptTab(tab, {
|
||||
elementIndex: newIndex,
|
||||
selectTab: tab == draggedTab,
|
||||
@@ -523,7 +536,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
- if (selectedTab) {
|
||||
+ if (false) {
|
||||
const newTab = gBrowser.adoptTab(selectedTab, {
|
||||
elementIndex: indexForSelectedTab,
|
||||
selectTab: selectedTab == draggedTab,
|
||||
@@ -534,10 +547,6 @@
|
||||
}
|
||||
|
||||
// Restore tab selection
|
||||
- gBrowser.addRangeToMultiSelectedTabs(
|
||||
- this._tabbrowserTabs.dragAndDropElements[dropIndex],
|
||||
- this._tabbrowserTabs.dragAndDropElements[newIndex - 1]
|
||||
- );
|
||||
} else {
|
||||
// Pass true to disallow dropping javascript: or data: urls
|
||||
let links;
|
||||
@@ -584,6 +593,7 @@
|
||||
|
||||
let nextItem = this._tabbrowserTabs.dragAndDropElements[newIndex];
|
||||
let tabGroup = isTab(nextItem) && nextItem.group;
|
||||
@@ -110,7 +139,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
|
||||
gBrowser.loadTabs(urls, {
|
||||
inBackground,
|
||||
replace,
|
||||
@@ -621,7 +635,16 @@
|
||||
@@ -621,7 +631,16 @@
|
||||
this._expandGroupOnDrop(draggedTab);
|
||||
}
|
||||
this._resetTabsAfterDrop(draggedTab.ownerDocument);
|
||||
@@ -128,7 +157,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
|
||||
if (
|
||||
dt.mozUserCancelled ||
|
||||
dt.dropEffect != "none" ||
|
||||
@@ -825,7 +848,10 @@
|
||||
@@ -825,7 +844,10 @@
|
||||
_getDragTarget(event, { ignoreSides = false } = {}) {
|
||||
let { target } = event;
|
||||
while (target) {
|
||||
@@ -140,7 +169,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
|
||||
break;
|
||||
}
|
||||
target = target.parentNode;
|
||||
@@ -842,14 +868,17 @@
|
||||
@@ -842,14 +864,17 @@
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -160,7 +189,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
|
||||
!this._tabbrowserTabs.expandOnHover
|
||||
);
|
||||
}
|
||||
@@ -880,7 +909,8 @@
|
||||
@@ -880,7 +905,8 @@
|
||||
isTabGroupLabel(draggedTab) &&
|
||||
draggedTab._dragData?.expandGroupOnDrop
|
||||
) {
|
||||
@@ -170,7 +199,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1058,7 +1088,6 @@
|
||||
@@ -1058,7 +1084,6 @@
|
||||
// using updateDragImage. On Linux, we can use a panel.
|
||||
if (platform == "win" || platform == "macosx") {
|
||||
captureListener = function () {
|
||||
@@ -178,7 +207,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
|
||||
};
|
||||
} else {
|
||||
// Create a panel to use it in setDragImage
|
||||
@@ -1096,7 +1125,6 @@
|
||||
@@ -1096,7 +1121,6 @@
|
||||
);
|
||||
dragImageOffset = dragImageOffset * scale;
|
||||
}
|
||||
@@ -186,7 +215,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
|
||||
|
||||
// _dragData.offsetX/Y give the coordinates that the mouse should be
|
||||
// positioned relative to the corner of the new window created upon
|
||||
@@ -1115,7 +1143,7 @@
|
||||
@@ -1115,7 +1139,7 @@
|
||||
let dropEffect = this.getDropEffectForTabDrag(event);
|
||||
let isMovingInTabStrip = !fromTabList && dropEffect == "move";
|
||||
let collapseTabGroupDuringDrag =
|
||||
@@ -195,7 +224,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
|
||||
|
||||
tab._dragData = {
|
||||
offsetX: this._tabbrowserTabs.verticalMode
|
||||
@@ -1125,7 +1153,7 @@
|
||||
@@ -1125,7 +1149,7 @@
|
||||
? event.screenY - window.screenY - tabOffset
|
||||
: event.screenY - window.screenY,
|
||||
scrollPos:
|
||||
@@ -204,7 +233,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
|
||||
? this._tabbrowserTabs.pinnedTabsContainer.scrollPosition
|
||||
: this._tabbrowserTabs.arrowScrollbox.scrollPosition,
|
||||
screenX: event.screenX,
|
||||
@@ -1152,6 +1180,7 @@
|
||||
@@ -1152,6 +1176,7 @@
|
||||
|
||||
if (collapseTabGroupDuringDrag) {
|
||||
tab.group.collapsed = true;
|
||||
@@ -212,7 +241,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1176,6 +1205,7 @@
|
||||
@@ -1176,6 +1201,7 @@
|
||||
if (tabStripItemElement.hasAttribute("dragtarget")) {
|
||||
return;
|
||||
}
|
||||
@@ -220,7 +249,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
|
||||
let isPinned = tab.pinned;
|
||||
let numPinned = gBrowser.pinnedTabCount;
|
||||
let dragAndDropElements = this._tabbrowserTabs.dragAndDropElements;
|
||||
@@ -1601,7 +1631,6 @@
|
||||
@@ -1601,7 +1627,6 @@
|
||||
|
||||
for (let item of this._tabbrowserTabs.dragAndDropElements) {
|
||||
item = elementToMove(item);
|
||||
@@ -228,7 +257,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
|
||||
item.removeAttribute("multiselected-move-together");
|
||||
delete item._moveTogetherSelectedTabsData;
|
||||
}
|
||||
@@ -2429,7 +2458,6 @@
|
||||
@@ -2429,7 +2454,6 @@
|
||||
for (let item of this._tabbrowserTabs.dragAndDropElements) {
|
||||
this._resetGroupTarget(item);
|
||||
item = elementToMove(item);
|
||||
@@ -236,7 +265,7 @@ index 57800333445ec7850742145527e04ae8d504b0bb..65361da4791b6418705f364f750f409b
|
||||
}
|
||||
this._tabbrowserTabs.removeAttribute("movingtab-group");
|
||||
this._tabbrowserTabs.removeAttribute("movingtab-ungroup");
|
||||
@@ -2460,17 +2488,14 @@
|
||||
@@ -2460,17 +2484,14 @@
|
||||
tab.style.left = "";
|
||||
tab.style.top = "";
|
||||
tab.style.maxWidth = "";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/tabbrowser/content/tab.js b/browser/components/tabbrowser/content/tab.js
|
||||
index 6528da245d922e2ccdb59cbf8106055bc34d1e74..1cd3395961a80e3b48582794b5b5365c9b8386b3 100644
|
||||
index 6528da245d922e2ccdb59cbf8106055bc34d1e74..b5d5ac633c06d7d9c909ec9456a5f3c165a6b925 100644
|
||||
--- a/browser/components/tabbrowser/content/tab.js
|
||||
+++ b/browser/components/tabbrowser/content/tab.js
|
||||
@@ -21,6 +21,7 @@
|
||||
@@ -52,7 +52,7 @@ index 6528da245d922e2ccdb59cbf8106055bc34d1e74..1cd3395961a80e3b48582794b5b5365c
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -224,11 +227,21 @@
|
||||
@@ -224,11 +227,23 @@
|
||||
}
|
||||
|
||||
get visible() {
|
||||
@@ -64,7 +64,6 @@ index 6528da245d922e2ccdb59cbf8106055bc34d1e74..1cd3395961a80e3b48582794b5b5365c
|
||||
+ if (!this.isOpen || this.hidden || this.hasAttribute("zen-empty-tab")) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ // Selected tabs are always visible
|
||||
+ if (this.selected || this.multiselected || this.hasAttribute("folder-active")) return true;
|
||||
+ // Recursively check all parent groups
|
||||
@@ -75,11 +74,14 @@ index 6528da245d922e2ccdb59cbf8106055bc34d1e74..1cd3395961a80e3b48582794b5b5365c
|
||||
+ }
|
||||
+ currentParent = currentParent.group;
|
||||
+ }
|
||||
+ if (this.pinned && !this.hasAttribute("zen-essential") && gZenWorkspaces.activeWorkspaceElement?.hasCollapsedPinnedTabs) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
}
|
||||
|
||||
get hidden() {
|
||||
@@ -307,7 +320,7 @@
|
||||
@@ -307,7 +322,7 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -88,7 +90,7 @@ index 6528da245d922e2ccdb59cbf8106055bc34d1e74..1cd3395961a80e3b48582794b5b5365c
|
||||
}
|
||||
|
||||
get lastAccessed() {
|
||||
@@ -384,7 +397,18 @@
|
||||
@@ -384,7 +399,18 @@
|
||||
}
|
||||
|
||||
get group() {
|
||||
@@ -108,7 +110,7 @@ index 6528da245d922e2ccdb59cbf8106055bc34d1e74..1cd3395961a80e3b48582794b5b5365c
|
||||
}
|
||||
|
||||
get splitview() {
|
||||
@@ -489,6 +513,8 @@
|
||||
@@ -489,6 +515,8 @@
|
||||
this.style.MozUserFocus = "ignore";
|
||||
} else if (
|
||||
event.target.classList.contains("tab-close-button") ||
|
||||
@@ -117,7 +119,7 @@ index 6528da245d922e2ccdb59cbf8106055bc34d1e74..1cd3395961a80e3b48582794b5b5365c
|
||||
event.target.classList.contains("tab-icon-overlay") ||
|
||||
event.target.classList.contains("tab-audio-button")
|
||||
) {
|
||||
@@ -543,6 +569,10 @@
|
||||
@@ -543,6 +571,10 @@
|
||||
this.style.MozUserFocus = "";
|
||||
}
|
||||
|
||||
@@ -128,7 +130,7 @@ index 6528da245d922e2ccdb59cbf8106055bc34d1e74..1cd3395961a80e3b48582794b5b5365c
|
||||
on_click(event) {
|
||||
if (event.button != 0) {
|
||||
return;
|
||||
@@ -603,6 +633,14 @@
|
||||
@@ -603,6 +635,14 @@
|
||||
// (see tabbrowser-tabs 'click' handler).
|
||||
gBrowser.tabContainer._blockDblClick = true;
|
||||
}
|
||||
@@ -143,7 +145,7 @@ index 6528da245d922e2ccdb59cbf8106055bc34d1e74..1cd3395961a80e3b48582794b5b5365c
|
||||
}
|
||||
|
||||
on_dblclick(event) {
|
||||
@@ -626,6 +664,8 @@
|
||||
@@ -626,6 +666,8 @@
|
||||
animate: true,
|
||||
triggeringEvent: event,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js
|
||||
index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689b5f65e94 100644
|
||||
index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..c7c7e6dd8cacf5d2d13c48ad9bed8195d677420f 100644
|
||||
--- a/browser/components/tabbrowser/content/tabbrowser.js
|
||||
+++ b/browser/components/tabbrowser/content/tabbrowser.js
|
||||
@@ -398,6 +398,7 @@
|
||||
@@ -119,7 +119,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
|
||||
aTab.setAttribute("pinned", "true");
|
||||
this._updateTabBarForPinnedTabs();
|
||||
@@ -931,11 +994,18 @@
|
||||
@@ -931,11 +994,19 @@
|
||||
}
|
||||
|
||||
this.#handleTabMove(aTab, () => {
|
||||
@@ -133,13 +133,14 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
// and back into arrowscrollbox.
|
||||
aTab.removeAttribute("pinned");
|
||||
- this.tabContainer.arrowScrollbox.prepend(aTab);
|
||||
+ aTab.removeAttribute("zen-essential");
|
||||
+ if (!handled) {
|
||||
+ gZenWorkspaces.activeWorkspaceStrip.prepend(aTab);
|
||||
+ }
|
||||
});
|
||||
|
||||
aTab.style.marginInlineStart = "";
|
||||
@@ -1112,6 +1182,9 @@
|
||||
@@ -1112,6 +1183,9 @@
|
||||
|
||||
let LOCAL_PROTOCOLS = ["chrome:", "about:", "resource:", "data:"];
|
||||
|
||||
@@ -149,7 +150,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
if (
|
||||
aIconURL &&
|
||||
!LOCAL_PROTOCOLS.some(protocol => aIconURL.startsWith(protocol))
|
||||
@@ -1121,6 +1194,9 @@
|
||||
@@ -1121,6 +1195,9 @@
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -159,7 +160,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
|
||||
let browser = this.getBrowserForTab(aTab);
|
||||
browser.mIconURL = aIconURL;
|
||||
@@ -1393,7 +1469,6 @@
|
||||
@@ -1393,7 +1470,6 @@
|
||||
|
||||
// Preview mode should not reset the owner
|
||||
if (!this._previewMode && !oldTab.selected) {
|
||||
@@ -167,7 +168,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
}
|
||||
|
||||
let lastRelatedTab = this._lastRelatedTabMap.get(oldTab);
|
||||
@@ -1484,6 +1559,7 @@
|
||||
@@ -1484,6 +1560,7 @@
|
||||
if (!this._previewMode) {
|
||||
newTab.recordTimeFromUnloadToReload();
|
||||
newTab.updateLastAccessed();
|
||||
@@ -175,7 +176,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
oldTab.updateLastAccessed();
|
||||
// if this is the foreground window, update the last-seen timestamps.
|
||||
if (this.ownerGlobal == BrowserWindowTracker.getTopWindow()) {
|
||||
@@ -1636,6 +1712,9 @@
|
||||
@@ -1636,6 +1713,9 @@
|
||||
}
|
||||
|
||||
let activeEl = document.activeElement;
|
||||
@@ -185,7 +186,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
// If focus is on the old tab, move it to the new tab.
|
||||
if (activeEl == oldTab) {
|
||||
newTab.focus();
|
||||
@@ -1959,6 +2038,11 @@
|
||||
@@ -1959,6 +2039,11 @@
|
||||
}
|
||||
|
||||
_setTabLabel(aTab, aLabel, { beforeTabOpen, isContentTitle, isURL } = {}) {
|
||||
@@ -197,7 +198,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
if (!aLabel || aLabel.includes("about:reader?")) {
|
||||
return false;
|
||||
}
|
||||
@@ -2067,7 +2151,7 @@
|
||||
@@ -2067,7 +2152,7 @@
|
||||
newIndex = this.selectedTab._tPos + 1;
|
||||
}
|
||||
|
||||
@@ -206,7 +207,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
if (this.isTabGroupLabel(targetTab)) {
|
||||
throw new Error(
|
||||
"Replacing a tab group label with a tab is not supported"
|
||||
@@ -2342,6 +2426,7 @@
|
||||
@@ -2342,6 +2427,7 @@
|
||||
uriIsAboutBlank,
|
||||
userContextId,
|
||||
skipLoad,
|
||||
@@ -214,7 +215,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
} = {}) {
|
||||
let b = document.createXULElement("browser");
|
||||
// Use the JSM global to create the permanentKey, so that if the
|
||||
@@ -2415,8 +2500,7 @@
|
||||
@@ -2415,8 +2501,7 @@
|
||||
// we use a different attribute name for this?
|
||||
b.setAttribute("name", name);
|
||||
}
|
||||
@@ -224,7 +225,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
b.setAttribute("transparent", "true");
|
||||
}
|
||||
|
||||
@@ -2581,7 +2665,7 @@
|
||||
@@ -2581,7 +2666,7 @@
|
||||
|
||||
let panel = this.getPanel(browser);
|
||||
let uniqueId = this._generateUniquePanelID();
|
||||
@@ -233,7 +234,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
aTab.linkedPanel = uniqueId;
|
||||
|
||||
// Inject the <browser> into the DOM if necessary.
|
||||
@@ -2640,8 +2724,8 @@
|
||||
@@ -2640,8 +2725,8 @@
|
||||
// If we transitioned from one browser to two browsers, we need to set
|
||||
// hasSiblings=false on both the existing browser and the new browser.
|
||||
if (this.tabs.length == 2) {
|
||||
@@ -244,7 +245,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
} else {
|
||||
aTab.linkedBrowser.browsingContext.hasSiblings = this.tabs.length > 1;
|
||||
}
|
||||
@@ -2828,7 +2912,6 @@
|
||||
@@ -2828,7 +2913,6 @@
|
||||
this.selectedTab = this.addTrustedTab(BROWSER_NEW_TAB_URL, {
|
||||
tabIndex: tab._tPos + 1,
|
||||
userContextId: tab.userContextId,
|
||||
@@ -252,7 +253,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
focusUrlBar: true,
|
||||
});
|
||||
resolve(this.selectedBrowser);
|
||||
@@ -2938,6 +3021,9 @@
|
||||
@@ -2938,6 +3022,9 @@
|
||||
schemelessInput,
|
||||
hasValidUserGestureActivation = false,
|
||||
textDirectiveUserActivation = false,
|
||||
@@ -262,7 +263,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
} = {}
|
||||
) {
|
||||
// all callers of addTab that pass a params object need to pass
|
||||
@@ -2948,10 +3034,17 @@
|
||||
@@ -2948,10 +3035,17 @@
|
||||
);
|
||||
}
|
||||
|
||||
@@ -280,7 +281,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
// If we're opening a foreground tab, set the owner by default.
|
||||
ownerTab ??= inBackground ? null : this.selectedTab;
|
||||
|
||||
@@ -2959,6 +3052,7 @@
|
||||
@@ -2959,6 +3053,7 @@
|
||||
if (this.selectedTab.owner) {
|
||||
this.selectedTab.owner = null;
|
||||
}
|
||||
@@ -288,7 +289,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
|
||||
// Find the tab that opened this one, if any. This is used for
|
||||
// determining positioning, and inherited attributes such as the
|
||||
@@ -3011,6 +3105,22 @@
|
||||
@@ -3011,6 +3106,22 @@
|
||||
noInitialLabel,
|
||||
skipBackgroundNotify,
|
||||
});
|
||||
@@ -311,7 +312,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
if (insertTab) {
|
||||
// Insert the tab into the tab container in the correct position.
|
||||
this.#insertTabAtIndex(t, {
|
||||
@@ -3019,6 +3129,7 @@
|
||||
@@ -3019,6 +3130,7 @@
|
||||
ownerTab,
|
||||
openerTab,
|
||||
pinned,
|
||||
@@ -319,7 +320,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
bulkOrderedOpen,
|
||||
tabGroup: tabGroup ?? openerTab?.group,
|
||||
});
|
||||
@@ -3037,6 +3148,7 @@
|
||||
@@ -3037,6 +3149,7 @@
|
||||
openWindowInfo,
|
||||
skipLoad,
|
||||
triggeringRemoteType,
|
||||
@@ -327,7 +328,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
}));
|
||||
|
||||
if (focusUrlBar) {
|
||||
@@ -3161,6 +3273,12 @@
|
||||
@@ -3161,6 +3274,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,7 +341,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
// Additionally send pinned tab events
|
||||
if (pinned) {
|
||||
this.#notifyPinnedStatus(t);
|
||||
@@ -3375,6 +3493,7 @@
|
||||
@@ -3375,6 +3494,7 @@
|
||||
isAdoptingGroup = false,
|
||||
isUserTriggered = false,
|
||||
telemetryUserCreateSource = "unknown",
|
||||
@@ -348,7 +349,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
} = {}
|
||||
) {
|
||||
if (
|
||||
@@ -3385,9 +3504,6 @@
|
||||
@@ -3385,9 +3505,6 @@
|
||||
!this.isSplitViewWrapper(tabOrSplitView)
|
||||
)
|
||||
) {
|
||||
@@ -358,7 +359,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
}
|
||||
|
||||
if (!color) {
|
||||
@@ -3408,9 +3524,14 @@
|
||||
@@ -3408,9 +3525,14 @@
|
||||
label,
|
||||
isAdoptingGroup
|
||||
);
|
||||
@@ -375,7 +376,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
);
|
||||
group.addTabs(tabsAndSplitViews);
|
||||
|
||||
@@ -3531,7 +3652,7 @@
|
||||
@@ -3531,7 +3653,7 @@
|
||||
}
|
||||
|
||||
this.#handleTabMove(tab, () =>
|
||||
@@ -384,7 +385,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3599,6 +3720,7 @@
|
||||
@@ -3599,6 +3721,7 @@
|
||||
color: group.color,
|
||||
insertBefore: newTabs[0],
|
||||
isAdoptingGroup: true,
|
||||
@@ -392,7 +393,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3746,6 +3868,7 @@
|
||||
@@ -3746,6 +3869,7 @@
|
||||
openWindowInfo,
|
||||
skipLoad,
|
||||
triggeringRemoteType,
|
||||
@@ -400,7 +401,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
}
|
||||
) {
|
||||
// If we don't have a preferred remote type (or it is `NOT_REMOTE`), and
|
||||
@@ -3815,6 +3938,7 @@
|
||||
@@ -3815,6 +3939,7 @@
|
||||
openWindowInfo,
|
||||
name,
|
||||
skipLoad,
|
||||
@@ -408,7 +409,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4003,7 +4127,7 @@
|
||||
@@ -4003,7 +4128,7 @@
|
||||
// Add a new tab if needed.
|
||||
if (!tab) {
|
||||
let createLazyBrowser =
|
||||
@@ -417,7 +418,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
|
||||
let url = "about:blank";
|
||||
if (tabData.entries?.length) {
|
||||
@@ -4040,8 +4164,10 @@
|
||||
@@ -4040,8 +4165,10 @@
|
||||
insertTab: false,
|
||||
skipLoad: true,
|
||||
preferredRemoteType,
|
||||
@@ -429,7 +430,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
if (select) {
|
||||
tabToSelect = tab;
|
||||
}
|
||||
@@ -4053,7 +4179,8 @@
|
||||
@@ -4053,7 +4180,8 @@
|
||||
this.pinTab(tab);
|
||||
// Then ensure all the tab open/pinning information is sent.
|
||||
this._fireTabOpen(tab, {});
|
||||
@@ -439,7 +440,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
let { groupId } = tabData;
|
||||
const tabGroup = tabGroupWorkingData.get(groupId);
|
||||
// if a tab refers to a tab group we don't know, skip any group
|
||||
@@ -4067,7 +4194,10 @@
|
||||
@@ -4067,7 +4195,10 @@
|
||||
tabGroup.stateData.id,
|
||||
tabGroup.stateData.color,
|
||||
tabGroup.stateData.collapsed,
|
||||
@@ -451,7 +452,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
);
|
||||
tabsFragment.appendChild(tabGroup.node);
|
||||
}
|
||||
@@ -4112,9 +4242,23 @@
|
||||
@@ -4112,9 +4243,23 @@
|
||||
// to remove the old selected tab.
|
||||
if (tabToSelect) {
|
||||
let leftoverTab = this.selectedTab;
|
||||
@@ -467,15 +468,15 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
+ gZenWorkspaces._initialTab._shouldRemove = true;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
+ }
|
||||
+ else {
|
||||
+ gZenWorkspaces._tabToRemoveForEmpty = this.selectedTab;
|
||||
+ }
|
||||
}
|
||||
+ this._hasAlreadyInitializedZenSessionStore = true;
|
||||
|
||||
if (tabs.length > 1 || !tabs[0].selected) {
|
||||
this._updateTabsAfterInsert();
|
||||
@@ -4305,11 +4449,14 @@
|
||||
@@ -4305,11 +4450,14 @@
|
||||
if (ownerTab) {
|
||||
tab.owner = ownerTab;
|
||||
}
|
||||
@@ -491,7 +492,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
if (
|
||||
!bulkOrderedOpen &&
|
||||
((openerTab &&
|
||||
@@ -4321,7 +4468,7 @@
|
||||
@@ -4321,7 +4469,7 @@
|
||||
let lastRelatedTab =
|
||||
openerTab && this._lastRelatedTabMap.get(openerTab);
|
||||
let previousTab = lastRelatedTab || openerTab || this.selectedTab;
|
||||
@@ -500,7 +501,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
tabGroup = previousTab.group;
|
||||
}
|
||||
if (
|
||||
@@ -4337,7 +4484,7 @@
|
||||
@@ -4337,7 +4485,7 @@
|
||||
previousTab.splitview
|
||||
) + 1;
|
||||
} else if (previousTab.visible) {
|
||||
@@ -509,7 +510,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
} else if (previousTab == FirefoxViewHandler.tab) {
|
||||
elementIndex = 0;
|
||||
}
|
||||
@@ -4365,14 +4512,14 @@
|
||||
@@ -4365,14 +4513,14 @@
|
||||
}
|
||||
// Ensure index is within bounds.
|
||||
if (tab.pinned) {
|
||||
@@ -528,7 +529,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
|
||||
if (pinned && !itemAfter?.pinned) {
|
||||
itemAfter = null;
|
||||
@@ -4385,7 +4532,7 @@
|
||||
@@ -4385,7 +4533,7 @@
|
||||
|
||||
this.tabContainer._invalidateCachedTabs();
|
||||
|
||||
@@ -537,7 +538,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
if (
|
||||
(this.isTab(itemAfter) && itemAfter.group == tabGroup) ||
|
||||
this.isSplitViewWrapper(itemAfter)
|
||||
@@ -4416,7 +4563,11 @@
|
||||
@@ -4416,7 +4564,11 @@
|
||||
const tabContainer = pinned
|
||||
? this.tabContainer.pinnedTabsContainer
|
||||
: this.tabContainer;
|
||||
@@ -549,7 +550,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
}
|
||||
|
||||
if (tab.group?.collapsed) {
|
||||
@@ -4431,6 +4582,7 @@
|
||||
@@ -4431,6 +4583,7 @@
|
||||
if (pinned) {
|
||||
this._updateTabBarForPinnedTabs();
|
||||
}
|
||||
@@ -557,7 +558,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
|
||||
TabBarVisibility.update();
|
||||
}
|
||||
@@ -4983,6 +5135,7 @@
|
||||
@@ -4983,6 +5136,7 @@
|
||||
telemetrySource,
|
||||
} = {}
|
||||
) {
|
||||
@@ -565,7 +566,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
// When 'closeWindowWithLastTab' pref is enabled, closing all tabs
|
||||
// can be considered equivalent to closing the window.
|
||||
if (
|
||||
@@ -5072,6 +5225,7 @@
|
||||
@@ -5072,6 +5226,7 @@
|
||||
if (lastToClose) {
|
||||
this.removeTab(lastToClose, aParams);
|
||||
}
|
||||
@@ -573,7 +574,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
@@ -5110,6 +5264,12 @@
|
||||
@@ -5110,6 +5265,12 @@
|
||||
aTab._closeTimeNoAnimTimerId = Glean.browserTabclose.timeNoAnim.start();
|
||||
}
|
||||
|
||||
@@ -586,7 +587,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
// Handle requests for synchronously removing an already
|
||||
// asynchronously closing tab.
|
||||
if (!animate && aTab.closing) {
|
||||
@@ -5124,6 +5284,9 @@
|
||||
@@ -5124,6 +5285,9 @@
|
||||
// state).
|
||||
let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width;
|
||||
let isLastTab = this.#isLastTabInWindow(aTab);
|
||||
@@ -596,7 +597,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
if (
|
||||
!this._beginRemoveTab(aTab, {
|
||||
closeWindowFastpath: true,
|
||||
@@ -5172,7 +5335,13 @@
|
||||
@@ -5172,7 +5336,13 @@
|
||||
// We're not animating, so we can cancel the animation stopwatch.
|
||||
Glean.browserTabclose.timeAnim.cancel(aTab._closeTimeAnimTimerId);
|
||||
aTab._closeTimeAnimTimerId = null;
|
||||
@@ -611,7 +612,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5306,7 +5475,7 @@
|
||||
@@ -5306,7 +5476,7 @@
|
||||
closeWindowWithLastTab != null
|
||||
? closeWindowWithLastTab
|
||||
: !window.toolbar.visible ||
|
||||
@@ -620,7 +621,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
|
||||
if (closeWindow) {
|
||||
// We've already called beforeunload on all the relevant tabs if we get here,
|
||||
@@ -5330,6 +5499,7 @@
|
||||
@@ -5330,6 +5500,7 @@
|
||||
|
||||
newTab = true;
|
||||
}
|
||||
@@ -628,7 +629,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
aTab._endRemoveArgs = [closeWindow, newTab];
|
||||
|
||||
// swapBrowsersAndCloseOther will take care of closing the window without animation.
|
||||
@@ -5370,13 +5540,7 @@
|
||||
@@ -5370,13 +5541,7 @@
|
||||
aTab._mouseleave();
|
||||
|
||||
if (newTab) {
|
||||
@@ -643,7 +644,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
} else {
|
||||
TabBarVisibility.update();
|
||||
}
|
||||
@@ -5509,6 +5673,7 @@
|
||||
@@ -5509,6 +5674,7 @@
|
||||
this.tabs[i]._tPos = i;
|
||||
}
|
||||
|
||||
@@ -651,7 +652,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
if (!this._windowIsClosing) {
|
||||
// update tab close buttons state
|
||||
this.tabContainer._updateCloseButtons();
|
||||
@@ -5732,6 +5897,7 @@
|
||||
@@ -5732,6 +5898,7 @@
|
||||
}
|
||||
|
||||
let excludeTabs = new Set(aExcludeTabs);
|
||||
@@ -659,7 +660,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
|
||||
// If this tab has a successor, it should be selectable, since
|
||||
// hiding or closing a tab removes that tab as a successor.
|
||||
@@ -5744,15 +5910,22 @@
|
||||
@@ -5744,15 +5911,22 @@
|
||||
!excludeTabs.has(aTab.owner) &&
|
||||
Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose")
|
||||
) {
|
||||
@@ -684,7 +685,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
let tab = this.tabContainer.findNextTab(aTab, {
|
||||
direction: 1,
|
||||
filter: _tab => remainingTabs.includes(_tab),
|
||||
@@ -5766,7 +5939,7 @@
|
||||
@@ -5766,7 +5940,7 @@
|
||||
}
|
||||
|
||||
if (tab) {
|
||||
@@ -693,7 +694,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
}
|
||||
|
||||
// If no qualifying visible tab was found, see if there is a tab in
|
||||
@@ -5787,7 +5960,7 @@
|
||||
@@ -5787,7 +5961,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
@@ -702,7 +703,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
}
|
||||
|
||||
_blurTab(aTab) {
|
||||
@@ -5798,7 +5971,7 @@
|
||||
@@ -5798,7 +5972,7 @@
|
||||
* @returns {boolean}
|
||||
* False if swapping isn't permitted, true otherwise.
|
||||
*/
|
||||
@@ -711,7 +712,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
// Do not allow transfering a private tab to a non-private window
|
||||
// and vice versa.
|
||||
if (
|
||||
@@ -5852,6 +6025,7 @@
|
||||
@@ -5852,6 +6026,7 @@
|
||||
// fire the beforeunload event in the process. Close the other
|
||||
// window if this was its last tab.
|
||||
if (
|
||||
@@ -719,7 +720,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
!remoteBrowser._beginRemoveTab(aOtherTab, {
|
||||
adoptedByTab: aOurTab,
|
||||
closeWindowWithLastTab: true,
|
||||
@@ -5863,7 +6037,7 @@
|
||||
@@ -5863,7 +6038,7 @@
|
||||
// If this is the last tab of the window, hide the window
|
||||
// immediately without animation before the docshell swap, to avoid
|
||||
// about:blank being painted.
|
||||
@@ -728,7 +729,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
if (closeWindow) {
|
||||
let win = aOtherTab.ownerGlobal;
|
||||
win.windowUtils.suppressAnimation(true);
|
||||
@@ -5987,11 +6161,13 @@
|
||||
@@ -5987,11 +6162,13 @@
|
||||
}
|
||||
|
||||
// Finish tearing down the tab that's going away.
|
||||
@@ -742,7 +743,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
|
||||
this.setTabTitle(aOurTab);
|
||||
|
||||
@@ -6193,10 +6369,10 @@
|
||||
@@ -6193,10 +6370,10 @@
|
||||
SessionStore.deleteCustomTabValue(aTab, "hiddenBy");
|
||||
}
|
||||
|
||||
@@ -755,7 +756,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
aTab.selected ||
|
||||
aTab.closing ||
|
||||
// Tabs that are sharing the screen, microphone or camera cannot be hidden.
|
||||
@@ -6254,7 +6430,8 @@
|
||||
@@ -6254,7 +6431,8 @@
|
||||
*
|
||||
* @param {MozTabbrowserTab|MozTabbrowserTabGroup|MozTabbrowserTabGroup.labelElement} aTab
|
||||
*/
|
||||
@@ -765,7 +766,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
if (this.tabs.length == 1) {
|
||||
return null;
|
||||
}
|
||||
@@ -6278,12 +6455,14 @@
|
||||
@@ -6278,12 +6456,14 @@
|
||||
}
|
||||
|
||||
// tell a new window to take the "dropped" tab
|
||||
@@ -776,12 +777,12 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
options,
|
||||
aTab
|
||||
);
|
||||
+ win._zenStartupSyncFlag = zenForceSync ? 'synced' : 'unsynced';
|
||||
+ win._zenStartupSyncFlag = (zenForceSync || !Services.prefs.getBoolPref("zen.tabs.dnd-open-blank-window", true)) ? 'synced' : 'unsynced';
|
||||
+ return win;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6388,7 +6567,7 @@
|
||||
@@ -6388,7 +6568,7 @@
|
||||
* `true` if element is a `<tab-group>`
|
||||
*/
|
||||
isTabGroup(element) {
|
||||
@@ -790,7 +791,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6473,8 +6652,8 @@
|
||||
@@ -6473,8 +6653,8 @@
|
||||
}
|
||||
|
||||
// Don't allow mixing pinned and unpinned tabs.
|
||||
@@ -801,7 +802,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
} else {
|
||||
tabIndex = Math.max(tabIndex, this.pinnedTabCount);
|
||||
}
|
||||
@@ -6500,10 +6679,16 @@
|
||||
@@ -6500,10 +6680,16 @@
|
||||
this.#handleTabMove(
|
||||
element,
|
||||
() => {
|
||||
@@ -820,7 +821,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
if (neighbor && this.isTab(element) && tabIndex > element._tPos) {
|
||||
neighbor.after(element);
|
||||
} else {
|
||||
@@ -6561,23 +6746,31 @@
|
||||
@@ -6561,23 +6747,31 @@
|
||||
#moveTabNextTo(element, targetElement, moveBefore = false, metricsContext) {
|
||||
if (this.isTabGroupLabel(targetElement)) {
|
||||
targetElement = targetElement.group;
|
||||
@@ -858,7 +859,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
} else if (!element.pinned && targetElement && targetElement.pinned) {
|
||||
// If the caller asks to move an unpinned element next to a pinned
|
||||
// tab, move the unpinned element to be the first unpinned element
|
||||
@@ -6590,14 +6783,34 @@
|
||||
@@ -6590,14 +6784,38 @@
|
||||
// move the tab group right before the first unpinned tab.
|
||||
// 4. Moving a tab group and the first unpinned tab is grouped:
|
||||
// move the tab group right before the first unpinned tab's tab group.
|
||||
@@ -872,6 +873,10 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
+ if (!gZenFolders.canDropElement(element, targetElement)) {
|
||||
+ element = element.group;
|
||||
+ }
|
||||
+ if (!element.hasAttribute('zen-essential') && targetElement?.hasAttribute('zen-essential')) {
|
||||
+ targetElement = null;
|
||||
+ moveBefore = false;
|
||||
+ }
|
||||
+ // It is necessary to place the check below to avoid inserting an element
|
||||
+ // inside when the split group is the last element.
|
||||
+ if (targetElement?.group?.hasAttribute("split-view-group")) {
|
||||
@@ -894,7 +899,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
element.pinned
|
||||
? this.tabContainer.pinnedTabsContainer
|
||||
: this.tabContainer;
|
||||
@@ -6606,7 +6819,7 @@
|
||||
@@ -6606,11 +6824,15 @@
|
||||
element,
|
||||
() => {
|
||||
if (moveBefore) {
|
||||
@@ -903,7 +908,15 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
} else if (targetElement) {
|
||||
targetElement.after(element);
|
||||
} else {
|
||||
@@ -6676,10 +6889,10 @@
|
||||
+ if (element.pinned) {
|
||||
+ getContainer().prepend(element);
|
||||
+ } else {
|
||||
getContainer().appendChild(element);
|
||||
+ }
|
||||
}
|
||||
},
|
||||
metricsContext
|
||||
@@ -6676,10 +6898,10 @@
|
||||
* @param {TabMetricsContext} [metricsContext]
|
||||
*/
|
||||
moveTabToExistingGroup(aTab, aGroup, metricsContext) {
|
||||
@@ -916,7 +929,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
return;
|
||||
}
|
||||
if (aTab.group && aTab.group.id === aGroup.id) {
|
||||
@@ -6751,6 +6964,7 @@
|
||||
@@ -6751,6 +6973,7 @@
|
||||
|
||||
let state = {
|
||||
tabIndex: tab._tPos,
|
||||
@@ -924,7 +937,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
};
|
||||
if (tab.visible) {
|
||||
state.elementIndex = tab.elementIndex;
|
||||
@@ -6777,7 +6991,7 @@
|
||||
@@ -6777,7 +7000,7 @@
|
||||
let changedTabGroup =
|
||||
previousTabState.tabGroupId != currentTabState.tabGroupId;
|
||||
|
||||
@@ -933,7 +946,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
tab.dispatchEvent(
|
||||
new CustomEvent("TabMove", {
|
||||
bubbles: true,
|
||||
@@ -6818,6 +7032,10 @@
|
||||
@@ -6818,6 +7041,10 @@
|
||||
|
||||
moveActionCallback();
|
||||
|
||||
@@ -944,7 +957,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
// Clear tabs cache after moving nodes because the order of tabs may have
|
||||
// changed.
|
||||
this.tabContainer._invalidateCachedTabs();
|
||||
@@ -6869,6 +7087,19 @@
|
||||
@@ -6869,6 +7096,18 @@
|
||||
* The new tab in the current window, null if the tab couldn't be adopted.
|
||||
*/
|
||||
adoptTab(aTab, { elementIndex, tabIndex, selectTab = false } = {}) {
|
||||
@@ -959,12 +972,11 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
+ }
|
||||
+ return thisTab;
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
// Swap the dropped tab with a new one we create and then close
|
||||
// it in the other window (making it seem to have moved between
|
||||
// windows). We also ensure that the tab we create to swap into has
|
||||
@@ -6910,6 +7141,8 @@
|
||||
@@ -6910,6 +7149,8 @@
|
||||
params.userContextId = aTab.getAttribute("usercontextid");
|
||||
}
|
||||
let newTab = this.addWebTab("about:blank", params);
|
||||
@@ -973,7 +985,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
let newBrowser = this.getBrowserForTab(newTab);
|
||||
|
||||
aTab.container.tabDragAndDrop.finishAnimateTabMove();
|
||||
@@ -7718,7 +7951,7 @@
|
||||
@@ -7718,7 +7959,7 @@
|
||||
// preventDefault(). It will still raise the window if appropriate.
|
||||
break;
|
||||
}
|
||||
@@ -982,7 +994,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
window.focus();
|
||||
aEvent.preventDefault();
|
||||
break;
|
||||
@@ -7735,7 +7968,6 @@
|
||||
@@ -7735,7 +7976,6 @@
|
||||
}
|
||||
case "TabGroupCollapse":
|
||||
aEvent.target.tabs.forEach(tab => {
|
||||
@@ -990,7 +1002,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
});
|
||||
break;
|
||||
case "TabGroupCreateByUser":
|
||||
@@ -7895,7 +8127,9 @@
|
||||
@@ -7895,7 +8135,9 @@
|
||||
|
||||
let filter = this._tabFilters.get(tab);
|
||||
if (filter) {
|
||||
@@ -1000,7 +1012,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
|
||||
let listener = this._tabListeners.get(tab);
|
||||
if (listener) {
|
||||
@@ -8698,6 +8932,7 @@
|
||||
@@ -8698,6 +8940,7 @@
|
||||
aWebProgress.isTopLevel
|
||||
) {
|
||||
this.mTab.setAttribute("busy", "true");
|
||||
@@ -1008,7 +1020,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
gBrowser._tabAttrModified(this.mTab, ["busy"]);
|
||||
this.mTab._notselectedsinceload = !this.mTab.selected;
|
||||
}
|
||||
@@ -8778,6 +9013,7 @@
|
||||
@@ -8778,6 +9021,7 @@
|
||||
// known defaults. Note we use the original URL since about:newtab
|
||||
// redirects to a prerendered page.
|
||||
const shouldRemoveFavicon =
|
||||
@@ -1016,7 +1028,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..2ab8633d0378e5a25cf75c50b29d4689
|
||||
!this.mBrowser.mIconURL &&
|
||||
!ignoreBlank &&
|
||||
!(originalLocation.spec in FAVICON_DEFAULTS);
|
||||
@@ -9803,7 +10039,7 @@ var TabContextMenu = {
|
||||
@@ -9803,7 +10047,7 @@ var TabContextMenu = {
|
||||
);
|
||||
contextUnpinSelectedTabs.hidden =
|
||||
!this.contextTab.pinned || !this.multiselected;
|
||||
|
||||
3
src/external-patches/librewolf/README.md
Normal file
3
src/external-patches/librewolf/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Patches imported from LibreWolf
|
||||
|
||||
Firefox sometimes makes changes without considering the impact on forks. This is the case of the patches that are imported from LibreWolf, which are already present in LibreWolf but not yet (or never) present in Firefox. Thanks to LibreWolf for making these patches available and for their work in maintaining them. We will keep these patches as long as they are needed, and we will remove them once they are no longer necessary (for example, when they are merged into Firefox or when the issue they solve is no longer present).
|
||||
12
src/external-patches/librewolf/firefox-in-ua.patch
Normal file
12
src/external-patches/librewolf/firefox-in-ua.patch
Normal file
@@ -0,0 +1,12 @@
|
||||
diff --git a/toolkit/moz.configure b/toolkit/moz.configure
|
||||
--- a/toolkit/moz.configure
|
||||
+++ b/toolkit/moz.configure
|
||||
@@ -28,7 +28,7 @@ project_flag(
|
||||
|
||||
project_flag(
|
||||
env="MOZ_APP_UA_NAME",
|
||||
- default="",
|
||||
+ default="Firefox",
|
||||
nargs=1,
|
||||
help="Application name in the User Agent string",
|
||||
)
|
||||
24
src/external-patches/manifest.json
Normal file
24
src/external-patches/manifest.json
Normal file
@@ -0,0 +1,24 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
[
|
||||
{
|
||||
"type": "phabricator",
|
||||
"id": "D279007",
|
||||
"name": "Fix MacOS Crash on Shutdown Firefox 149"
|
||||
},
|
||||
{
|
||||
"type": "local",
|
||||
"path": "firefox/no_liquid_glass_icon.patch"
|
||||
},
|
||||
{
|
||||
"type": "patch",
|
||||
"url": "https://codeberg.org/librewolf/source/raw/branch/main/patches/firefox-in-ua.patch",
|
||||
"dest": "librewolf",
|
||||
"replaces": {
|
||||
// They don't correctly export this patch, so we need to replace
|
||||
// the parameter's help description with the correct one.
|
||||
"application": "Application"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,13 +0,0 @@
|
||||
diff --git a/netwerk/protocol/http/moz.build b/netwerk/protocol/http/moz.build
|
||||
index d2330003caf35c43d6831fb0d356ece513906f78..76c2faf822ddaf645eb03d93380c58b4e3b510c0 100644
|
||||
--- a/netwerk/protocol/http/moz.build
|
||||
+++ b/netwerk/protocol/http/moz.build
|
||||
@@ -227,7 +227,7 @@ LOCAL_INCLUDES += [
|
||||
"/netwerk/url-classifier",
|
||||
]
|
||||
|
||||
-DEFINES["MOZ_APP_UA_NAME"] = f'"{CONFIG["MOZ_APP_UA_NAME"]}"'
|
||||
+DEFINES["MOZ_APP_UA_NAME"] = f'"Firefox"'
|
||||
|
||||
if CONFIG["MOZ_AUTH_EXTENSION"]:
|
||||
LOCAL_INCLUDES += [
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/toolkit/components/extensions/parent/ext-runtime.js b/toolkit/components/extensions/parent/ext-runtime.js
|
||||
index 0d7a3e505b6bd30548c6dda1504dd343a517b083..54400def5e02e886765fab68c3854a6b3c24ef2b 100644
|
||||
index 0d7a3e505b6bd30548c6dda1504dd343a517b083..fb6c6b4ef3eae24995a02f708ec41afd31d812ef 100644
|
||||
--- a/toolkit/components/extensions/parent/ext-runtime.js
|
||||
+++ b/toolkit/components/extensions/parent/ext-runtime.js
|
||||
@@ -333,7 +333,7 @@ this.runtime = class extends ExtensionAPIPersistent {
|
||||
@@ -7,7 +7,7 @@ index 0d7a3e505b6bd30548c6dda1504dd343a517b083..54400def5e02e886765fab68c3854a6b
|
||||
getBrowserInfo: function () {
|
||||
const { name, vendor, version, appBuildID } = Services.appinfo;
|
||||
- const info = { name, vendor, version, buildID: appBuildID };
|
||||
+ const info = { name: 'firefox', vendor, version: AppConstants.ZEN_FIREFOX_VERSION, buildID: appBuildID };
|
||||
+ const info = { name: 'Firefox', vendor, version: AppConstants.ZEN_FIREFOX_VERSION, buildID: appBuildID, zen: {version: AppConstants.MOZ_APP_VERSION_DISPLAY} };
|
||||
return Promise.resolve(info);
|
||||
},
|
||||
|
||||
|
||||
40
src/toolkit/xre/nsXREDirProvider-cpp.patch
Normal file
40
src/toolkit/xre/nsXREDirProvider-cpp.patch
Normal file
@@ -0,0 +1,40 @@
|
||||
diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp
|
||||
index 64456439499d449ce7f2861b1a5addbeecd61721..d0acdb3082b4805e2b8903f8044c97ddf29419bb 100644
|
||||
--- a/toolkit/xre/nsXREDirProvider.cpp
|
||||
+++ b/toolkit/xre/nsXREDirProvider.cpp
|
||||
@@ -1317,9 +1317,11 @@ nsresult nsXREDirProvider::AppendFromAppData(nsIFile* aFile, bool aIsDotted) {
|
||||
// Similar to nsXREDirProvider::AppendProfilePath.
|
||||
// TODO: Bug 1990407 - Evaluate if refactoring might be required there in the
|
||||
// future?
|
||||
- if (gAppData->profile) {
|
||||
+ // Use aIsDotted for a different purpose here, will probably break in the future
|
||||
+ if (gAppData->profile && aIsDotted) {
|
||||
nsAutoCString profile;
|
||||
profile = gAppData->profile;
|
||||
+ profile = "."_ns + nsDependentCString(gAppData->profile);
|
||||
MOZ_TRY(aFile->AppendRelativeNativePath(profile));
|
||||
} else {
|
||||
nsAutoCString vendor;
|
||||
@@ -1329,8 +1331,6 @@ nsresult nsXREDirProvider::AppendFromAppData(nsIFile* aFile, bool aIsDotted) {
|
||||
ToLowerCase(vendor);
|
||||
ToLowerCase(appName);
|
||||
|
||||
- MOZ_TRY(aFile->AppendRelativeNativePath(aIsDotted ? ("."_ns + vendor)
|
||||
- : vendor));
|
||||
MOZ_TRY(aFile->AppendRelativeNativePath(appName));
|
||||
}
|
||||
|
||||
@@ -1498,13 +1498,8 @@ nsresult nsXREDirProvider::GetLegacyOrXDGHomePath(const char* aHomeDir,
|
||||
|
||||
// If the build was made against a specific profile name, MOZ_APP_PROFILE=
|
||||
// then make sure we respect this and dont move to XDG directory
|
||||
- if (gAppData->profile) {
|
||||
- MOZ_TRY(NS_NewNativeLocalFile(nsDependentCString(aHomeDir),
|
||||
- getter_AddRefs(localDir)));
|
||||
- } else {
|
||||
MOZ_TRY(GetLegacyOrXDGConfigHome(aHomeDir, getter_AddRefs(localDir)));
|
||||
MOZ_TRY(localDir->Clone(getter_AddRefs(parentDir)));
|
||||
- }
|
||||
|
||||
MOZ_TRY(AppendFromAppData(localDir, false));
|
||||
}
|
||||
@@ -25,7 +25,7 @@
|
||||
content/browser/zen-styles/zen-panel-ui.css (../../zen/common/styles/zen-panel-ui.css)
|
||||
content/browser/zen-styles/zen-single-components.css (../../zen/common/styles/zen-single-components.css)
|
||||
content/browser/zen-styles/zen-sidebar.css (../../zen/common/styles/zen-sidebar.css)
|
||||
content/browser/zen-styles/zen-toolbar.css (../../zen/common/styles/zen-toolbar.css)
|
||||
* content/browser/zen-styles/zen-toolbar.css (../../zen/common/styles/zen-toolbar.css)
|
||||
content/browser/zen-styles/zen-browser-container.css (../../zen/common/styles/zen-browser-container.css)
|
||||
content/browser/zen-styles/zen-omnibox.css (../../zen/common/styles/zen-omnibox.css)
|
||||
content/browser/zen-styles/zen-popup.css (../../zen/common/styles/zen-popup.css)
|
||||
|
||||
@@ -98,6 +98,12 @@ export class nsZenMenuBar {
|
||||
</menu>`);
|
||||
document.getElementById("view-menu").after(spacesMenubar);
|
||||
document.getElementById("zen-spaces-menubar").addEventListener("popupshowing", () => {
|
||||
if (AppConstants.platform === "linux") {
|
||||
// On linux, there seems to be a bug where the menu freezes up and makes the browser
|
||||
// suppiciously unresponsive if we try to update the menu while it's opening.
|
||||
// See https://github.com/zen-browser/desktop/issues/12024
|
||||
return;
|
||||
}
|
||||
gZenWorkspaces.updateWorkspacesChangeContextMenu();
|
||||
});
|
||||
}
|
||||
@@ -106,7 +112,7 @@ export class nsZenMenuBar {
|
||||
const openUnsyncedWindowItem = window.MozXULElement.parseXULToFragment(
|
||||
`<toolbarbutton id="appMenu-new-zen-unsynced-window-button"
|
||||
class="subviewbutton"
|
||||
data-l10n-id="zen-menubar-new-unsynced-window"
|
||||
data-l10n-id="zen-appmenu-new-blank-window"
|
||||
key="zen-new-unsynced-window"
|
||||
command="cmd_zenNewNavigatorUnsynced"/>`
|
||||
).querySelector("toolbarbutton");
|
||||
@@ -117,7 +123,7 @@ export class nsZenMenuBar {
|
||||
window.MozXULElement.parseXULToFragment(`
|
||||
<menuitem id="menu_new_zen_unsynced_window"
|
||||
class="subviewbutton"
|
||||
data-l10n-id="zen-menubar-new-unsynced-window"
|
||||
data-l10n-id="zen-menubar-new-blank-window"
|
||||
key="zen-new-unsynced-window"
|
||||
command="cmd_zenNewNavigatorUnsynced"/>`)
|
||||
);
|
||||
|
||||
@@ -87,7 +87,6 @@ class ZenStartup {
|
||||
await delayedStartupPromise;
|
||||
await SessionStore.promiseAllWindowsRestored;
|
||||
delete gZenUIManager.promiseInitialized;
|
||||
this.#initSearchBar();
|
||||
gZenCompactModeManager.init();
|
||||
// Fix for https://github.com/zen-browser/desktop/issues/7605, specially in compact mode
|
||||
if (gURLBar.hasAttribute("breakout-extend")) {
|
||||
@@ -154,11 +153,6 @@ class ZenStartup {
|
||||
}
|
||||
}
|
||||
|
||||
#initSearchBar() {
|
||||
// Only focus the url bar
|
||||
gURLBar.focus();
|
||||
}
|
||||
|
||||
#checkForWelcomePage() {
|
||||
if (!Services.prefs.getBoolPref("zen.welcome-screen.seen", false)) {
|
||||
Services.prefs.setBoolPref("zen.welcome-screen.seen", true);
|
||||
|
||||
@@ -891,8 +891,8 @@ window.gZenVerticalTabsManager = {
|
||||
marginBottom: isLastItem() ? ["0px", "0px"] : [transform, "0px"],
|
||||
},
|
||||
{
|
||||
duration: 0.11,
|
||||
easing: "ease-out",
|
||||
duration: 0.075,
|
||||
easing: "easeOut",
|
||||
}
|
||||
)
|
||||
.then(() => {})
|
||||
@@ -913,8 +913,8 @@ window.gZenVerticalTabsManager = {
|
||||
filter: ["blur(1px)", "blur(0px)"],
|
||||
},
|
||||
{
|
||||
duration: 0.11,
|
||||
easing: "ease-out",
|
||||
duration: 0.075,
|
||||
easing: "easeOut",
|
||||
}
|
||||
)
|
||||
.then(() => {})
|
||||
@@ -949,7 +949,7 @@ window.gZenVerticalTabsManager = {
|
||||
},
|
||||
{
|
||||
duration: 0.075,
|
||||
easing: "ease-out",
|
||||
easing: "easeOut",
|
||||
}
|
||||
);
|
||||
},
|
||||
@@ -1055,7 +1055,7 @@ window.gZenVerticalTabsManager = {
|
||||
if (!this._hasSetSingleToolbar) {
|
||||
height = AppConstants.platform == "macosx" ? 34 : 32;
|
||||
} else if (gURLBar.getAttribute("breakout-extend") !== "true") {
|
||||
height = 40;
|
||||
height = 38;
|
||||
}
|
||||
if (typeof height !== "undefined") {
|
||||
gURLBar.style.setProperty("--urlbar-height", `${height}px`);
|
||||
@@ -1275,6 +1275,15 @@ window.gZenVerticalTabsManager = {
|
||||
appContentNavbarContaienr.append(windowButtons);
|
||||
}
|
||||
|
||||
if (
|
||||
this._hasSetSingleToolbar &&
|
||||
Services.prefs.getBoolPref("zen.view.overflow-webext-toolbar", true)
|
||||
) {
|
||||
topButtons.setAttribute("addon-webext-overflowtarget", "zen-overflow-extensions-list");
|
||||
} else {
|
||||
topButtons.setAttribute("addon-webext-overflowtarget", "overflowed-extensions-list");
|
||||
}
|
||||
|
||||
gZenCompactModeManager.updateCompactModeContext(isSingleToolbar);
|
||||
|
||||
// Always move the splitter next to the sidebar
|
||||
@@ -1403,7 +1412,8 @@ window.gZenVerticalTabsManager = {
|
||||
if (
|
||||
this._tabEdited ||
|
||||
((!Services.prefs.getBoolPref("zen.tabs.rename-tabs") ||
|
||||
Services.prefs.getBoolPref("browser.tabs.closeTabByDblclick")) &&
|
||||
(Services.prefs.getBoolPref("browser.tabs.closeTabByDblclick") &&
|
||||
event.type === "dblclick")) &&
|
||||
isTab) ||
|
||||
!gZenVerticalTabsManager._prefsSidebarExpanded
|
||||
) {
|
||||
|
||||
@@ -132,6 +132,7 @@
|
||||
}
|
||||
|
||||
#nav-bar {
|
||||
overflow: clip;
|
||||
border-top-color: transparent !important;
|
||||
|
||||
:root[zen-single-toolbar="true"] & {
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
|
||||
#urlbar:not([breakout-extend="true"]) {
|
||||
&:hover .urlbar-background {
|
||||
background-color: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.2)) !important;
|
||||
background-color: var(--zen-toolbar-element-bg-hover) !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,7 +309,7 @@
|
||||
order: 2;
|
||||
}
|
||||
|
||||
#notification-popup-box:not([open]) {
|
||||
#notification-popup-box:not([open]):not(:has(> [showing="true"])) {
|
||||
margin-inline-start: calc(-10px - 2 * var(--urlbar-icon-padding));
|
||||
opacity: 0;
|
||||
transition: all 0.2s;
|
||||
|
||||
48
src/zen/common/styles/zen-overflowing-addons.css
Normal file
48
src/zen/common/styles/zen-overflowing-addons.css
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#zen-overflow-extensions-list:not(:empty) {
|
||||
--uei-icon-size: 14px;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 8px 2px;
|
||||
padding-bottom: 0px;
|
||||
|
||||
& .unified-extensions-item {
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
& .toolbarbutton-badge-stack {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 8px 0;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
& .unified-extensions-item-action-button {
|
||||
background-color: var(--zen-toolbar-element-bg);
|
||||
height: 30px;
|
||||
margin: 0;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: var(--border-radius-medium);
|
||||
overflow: clip;
|
||||
padding: 0;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--zen-toolbar-element-bg-hover);
|
||||
}
|
||||
}
|
||||
|
||||
.unified-extensions-item-contents,
|
||||
.unified-extensions-item-menu-button,
|
||||
unified-extensions-item-messagebar-wrapper {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -177,6 +177,7 @@
|
||||
--toolbarbutton-border-radius: var(--tab-border-radius);
|
||||
--toolbarbutton-inner-padding: 6px;
|
||||
--toolbarbutton-outer-padding: 2px;
|
||||
color: color-mix(in srgb, currentColor 60%, transparent);
|
||||
|
||||
transition:
|
||||
background-color 0.1s,
|
||||
@@ -191,6 +192,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
#zen-sidebar-top-buttons toolbarbutton {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.zen-interactive-button {
|
||||
background: color-mix(in srgb, currentColor 6%, transparent) !important;
|
||||
transition:
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
|
||||
:host(:is(.anonymous-content-host, notification-message)),
|
||||
:root {
|
||||
:root:not([windowtype^="Browser:"]) {
|
||||
/* Default values */
|
||||
--zen-border-radius: 7px;
|
||||
--zen-primary-color: AccentColor;
|
||||
@@ -141,14 +141,11 @@
|
||||
--zen-button-padding: 0.6rem 1.2rem;
|
||||
|
||||
--zen-toolbar-element-bg: light-dark(
|
||||
color-mix(in oklch, var(--toolbox-textcolor) 10%, transparent),
|
||||
color-mix(in oklch, var(--toolbox-textcolor) 8%, transparent),
|
||||
color-mix(in oklch, var(--toolbox-textcolor) 15%, transparent)
|
||||
);
|
||||
|
||||
--zen-toolbar-element-bg-hover: light-dark(
|
||||
color-mix(in srgb, var(--zen-toolbar-element-bg) 75%, transparent),
|
||||
color-mix(in srgb, var(--zen-toolbar-element-bg) 60%, transparent)
|
||||
);
|
||||
--zen-toolbar-element-bg-hover: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.2));
|
||||
|
||||
/* Toolbar */
|
||||
--tab-selected-color-scheme: inherit !important;
|
||||
@@ -222,7 +219,7 @@
|
||||
--input-border-color: var(--zen-input-border-color) !important;
|
||||
--zen-themed-toolbar-bg-transparent: light-dark(var(--zen-branding-bg), #171717);
|
||||
|
||||
--zen-workspace-indicator-height: 46px;
|
||||
--zen-workspace-indicator-height: 44px;
|
||||
|
||||
&:not([zen-sidebar-expanded='true']) {
|
||||
--zen-workspace-indicator-height: 38px;
|
||||
@@ -231,10 +228,7 @@
|
||||
--toolbar-field-color: var(--toolbox-textcolor) !important;
|
||||
|
||||
&[zen-private-window='true'] {
|
||||
--zen-main-browser-background: linear-gradient(130deg,
|
||||
color-mix(in srgb, rgb(10, 6, 11) 80%, var(--zen-themed-toolbar-bg-transparent)) 0%,
|
||||
color-mix(in srgb, rgb(19, 7, 22) 80%, var(--zen-themed-toolbar-bg-transparent)) 100%
|
||||
);
|
||||
--zen-main-browser-background: color-mix(in srgb, rgb(11, 10, 11) 90%, var(--zen-themed-toolbar-bg-transparent));
|
||||
--zen-main-browser-background-toolbar: var(--zen-main-browser-background);
|
||||
--zen-primary-color: light-dark(rgb(93, 42, 107), rgb(110, 48, 125)) !important;
|
||||
--toolbox-textcolor: color-mix(in srgb, currentColor 95%, transparent) !important;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#nav-bar,
|
||||
#zen-sidebar-top-buttons {
|
||||
background: transparent;
|
||||
@@ -11,3 +12,5 @@
|
||||
:root[inDOMFullscreen="true"] #zen-appcontent-navbar-wrapper {
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
%include zen-overflowing-addons.css
|
||||
|
||||
@@ -121,8 +121,11 @@ export const ZenCustomizableUI = new (class {
|
||||
|
||||
#initCreateNewButton(window) {
|
||||
const button = window.document.getElementById("zen-create-new-button");
|
||||
button.addEventListener("command", (event) => {
|
||||
if (window.gZenWorkspaces.privateWindowOrDisabled) {
|
||||
// If we use "mousedown" event for private windows (which open a new tab on "click"), we might end up with
|
||||
// the urlbar flicking and therefore we use "command" event to avoid that.
|
||||
let isPrivateMode = window.gZenWorkspaces.privateWindowOrDisabled;
|
||||
button.addEventListener(isPrivateMode ? "command" : "mousedown", (event) => {
|
||||
if (isPrivateMode) {
|
||||
window.document.getElementById("cmd_newNavigatorTab").doCommand();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -10,9 +10,14 @@
|
||||
}
|
||||
|
||||
#zen-dragover-background {
|
||||
width: calc(100% - var(--zen-toolbox-padding) * 2 - 5px);
|
||||
width: calc(100% - var(--zen-toolbox-padding) * 2 - 7px);
|
||||
left: unset;
|
||||
right: calc(var(--zen-toolbox-padding) + 3px);
|
||||
transform: translateY(-4px);
|
||||
|
||||
:root:not([zen-single-toolbar="true"]) & {
|
||||
transform: translateY(calc(-100% - 2px));
|
||||
}
|
||||
}
|
||||
|
||||
#zen-tabbox-wrapper {
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
if (tabClone.hasAttribute("visuallyselected")) {
|
||||
tabClone.style.transform = "translate(-50%, -50%)";
|
||||
}
|
||||
} else if (AppConstants.platform !== "macosx") {
|
||||
} else if (AppConstants.platform !== "macosx" && !tab.isZenFolder) {
|
||||
// On windows and linux, we still don't add some extra opaqueness
|
||||
// for the tab to be more visible. This is a hacky workaround.
|
||||
// TODO: Make windows and linux DnD use nsZenDragAndDrop::mDragImageOpacity
|
||||
@@ -672,12 +672,20 @@
|
||||
if (!isTab(draggedTab)) {
|
||||
return;
|
||||
}
|
||||
const { clientX, clientY } = event;
|
||||
const { innerWidth, innerHeight } = window;
|
||||
let { screenX, clientX, screenY, clientY } = event;
|
||||
if (!screenX && !screenY) {
|
||||
return;
|
||||
}
|
||||
const { innerWidth: winWidth, innerHeight: winHeight } = window;
|
||||
let allowedMargin = Services.prefs.getIntPref("zen.tabs.dnd-outside-window-margin", 5);
|
||||
const isOutOfWindow =
|
||||
clientX < 0 || clientX > innerWidth || clientY < 0 || clientY > innerHeight;
|
||||
clientX <= allowedMargin ||
|
||||
clientX >= winWidth - allowedMargin ||
|
||||
clientY <= allowedMargin ||
|
||||
clientY >= winHeight - allowedMargin;
|
||||
if (isOutOfWindow && !this.#isOutOfWindow) {
|
||||
this.#isOutOfWindow = true;
|
||||
gZenViewSplitter.onBrowserDragEndToSplit(event, true);
|
||||
this.#maybeClearVerticalPinnedGridDragOver();
|
||||
this.clearSpaceSwitchTimer();
|
||||
this.clearDragOverVisuals();
|
||||
@@ -701,7 +709,7 @@
|
||||
this.originalDragImageArgs[1],
|
||||
this.originalDragImageArgs[2]
|
||||
);
|
||||
window.addEventListener("dragover", this.handle_windowDragEnter, {
|
||||
window.addEventListener("dragenter", this.handle_windowDragEnter, {
|
||||
once: true,
|
||||
capture: true,
|
||||
});
|
||||
@@ -716,20 +724,22 @@
|
||||
const dt = event.dataTransfer;
|
||||
const activeWorkspace = gZenWorkspaces.activeWorkspace;
|
||||
let draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
|
||||
if (
|
||||
isTab(draggedTab) &&
|
||||
!draggedTab.hasAttribute("zen-essential") &&
|
||||
draggedTab.getAttribute("zen-workspace-id") != activeWorkspace
|
||||
) {
|
||||
const movingTabs = draggedTab._dragData?.movingTabs || [draggedTab];
|
||||
for (let tab of movingTabs) {
|
||||
tab.setAttribute("zen-workspace-id", activeWorkspace);
|
||||
if (draggedTab.ownerGlobal === window) {
|
||||
if (
|
||||
!draggedTab.hasAttribute("zen-essential") &&
|
||||
draggedTab.getAttribute("zen-workspace-id") != activeWorkspace
|
||||
) {
|
||||
if (isTab(draggedTab)) {
|
||||
const movingTabs = draggedTab._dragData?.movingTabs || [draggedTab];
|
||||
for (let tab of movingTabs) {
|
||||
tab.setAttribute("zen-workspace-id", activeWorkspace);
|
||||
}
|
||||
gBrowser.selectedTab = draggedTab;
|
||||
} else if (isTabGroupLabel(draggedTab)) {
|
||||
draggedTab = draggedTab.group;
|
||||
gZenFolders.changeFolderToSpace(draggedTab, activeWorkspace, { hasDndSwitch: true });
|
||||
}
|
||||
}
|
||||
gBrowser.selectedTab = draggedTab;
|
||||
}
|
||||
if (isTabGroupLabel(draggedTab)) {
|
||||
draggedTab = draggedTab.group;
|
||||
gZenFolders.changeFolderToSpace(draggedTab, activeWorkspace, { hasDndSwitch: true });
|
||||
}
|
||||
gZenWorkspaces.updateTabsContainers();
|
||||
}
|
||||
@@ -759,7 +769,8 @@
|
||||
draggedTab.hasAttribute("zen-essential") ||
|
||||
draggedTab.getAttribute("zen-workspace-id") != gZenWorkspaces.activeWorkspace ||
|
||||
!dropElement.visible ||
|
||||
!draggedTab.visible
|
||||
!draggedTab.visible ||
|
||||
draggedTab.ownerGlobal !== window
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -848,21 +859,22 @@
|
||||
handle_dragend(event) {
|
||||
const dt = event.dataTransfer;
|
||||
const draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
|
||||
let ownerGlobal = draggedTab?.ownerGlobal;
|
||||
draggedTab.style.visibility = "";
|
||||
let currentEssenialContainer = gZenWorkspaces.getCurrentEssentialsContainer();
|
||||
let currentEssenialContainer = ownerGlobal.gZenWorkspaces.getCurrentEssentialsContainer();
|
||||
if (currentEssenialContainer?.essentialsPromo) {
|
||||
currentEssenialContainer.essentialsPromo.remove();
|
||||
}
|
||||
// We also call it here to ensure we clear any highlight if the drop happened
|
||||
// outside of a valid drop target.
|
||||
gZenFolders.highlightGroupOnDragOver(null);
|
||||
ownerGlobal.gZenFolders.highlightGroupOnDragOver(null);
|
||||
this.ZenDragAndDropService.onDragEnd();
|
||||
super.handle_dragend(event);
|
||||
this.#removeDragOverBackground();
|
||||
gZenPinnedTabManager.removeTabContainersDragoverClass();
|
||||
ownerGlobal.gZenPinnedTabManager.removeTabContainersDragoverClass();
|
||||
this.#maybeClearVerticalPinnedGridDragOver();
|
||||
this.originalDragImageArgs = [];
|
||||
window.removeEventListener("dragover", this.handle_windowDragEnter, { capture: true });
|
||||
window.removeEventListener("dragenter", this.handle_windowDragEnter, { capture: true });
|
||||
this.#isOutOfWindow = false;
|
||||
if (this._browserDragImageWrapper) {
|
||||
this._browserDragImageWrapper.remove();
|
||||
@@ -872,9 +884,9 @@
|
||||
this._tempDragImageParent.remove();
|
||||
delete this._tempDragImageParent;
|
||||
}
|
||||
delete gZenCompactModeManager._isTabBeingDragged;
|
||||
delete ownerGlobal.gZenCompactModeManager._isTabBeingDragged;
|
||||
if (dt.dropEffect !== "move") {
|
||||
gZenCompactModeManager._clearAllHoverStates();
|
||||
ownerGlobal.gZenCompactModeManager._clearAllHoverStates();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -924,11 +936,13 @@
|
||||
let dropElementFromEvent = event.target.closest(dropZoneSelector);
|
||||
dropElement = dropElementFromEvent || dropElement;
|
||||
if (!dropElementFromEvent) {
|
||||
let hoveringPeriphery = !!event.target.closest("#tabbrowser-arrowscrollbox-periphery");
|
||||
let hoveringPeriphery = !!event.target.closest(
|
||||
":is(#tabbrowser-arrowscrollbox-periphery, .pinned-tabs-container-separator)"
|
||||
);
|
||||
if (event.target.classList.contains("zen-workspace-empty-space") || hoveringPeriphery) {
|
||||
let lastTab = gBrowser.tabs.at(-1);
|
||||
dropElement =
|
||||
(hoveringPeriphery
|
||||
(hoveringPeriphery && Services.prefs.getBoolPref("zen.view.show-newtab-button-top")
|
||||
? this._tabbrowserTabs.ariaFocusableItems.at(
|
||||
gBrowser._numVisiblePinTabsWithoutCollapsed
|
||||
)
|
||||
@@ -948,7 +962,8 @@
|
||||
dropElement = dragData.dropElement;
|
||||
dropBefore = dragData.dropBefore;
|
||||
}
|
||||
if (!dropElement) {
|
||||
// Essentials should be properly handled by ::animateVerticalPinnedGridDragOver
|
||||
if (!dropElement || dropElement.hasAttribute("zen-essential")) {
|
||||
this.clearDragOverVisuals();
|
||||
return null;
|
||||
}
|
||||
@@ -1277,6 +1292,9 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line mozilla/valid-services
|
||||
Services.zen.playHapticFeedback();
|
||||
|
||||
dragData.animDropElementIndex = newIndex;
|
||||
dragData.dropElement = tabs[Math.min(newIndex, tabs.length - 1)];
|
||||
dragData.dropBefore = newIndex < tabs.length;
|
||||
|
||||
@@ -21,7 +21,7 @@ export class nsZenFolder extends MozTabbrowserTabGroup {
|
||||
|
||||
static rawIcon = new DOMParser().parseFromString(
|
||||
`
|
||||
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="28" height="28" viewBox="0 0 27 27" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient gradientUnits="userSpaceOnUse" x1="14" y1="5.625" x2="14" y2="22.375" id="gradient-0">
|
||||
<stop offset="0" style="stop-color: rgb(255, 255, 255)"/>
|
||||
@@ -242,7 +242,7 @@ export class nsZenFolder extends MozTabbrowserTabGroup {
|
||||
}
|
||||
|
||||
get resetButton() {
|
||||
return this.labelElement.parentElement.querySelector(".tab-reset-button");
|
||||
return this.labelElement.parentElement?.querySelector(".tab-reset-button") ?? null;
|
||||
}
|
||||
|
||||
unloadAllTabs(event) {
|
||||
|
||||
@@ -1038,43 +1038,47 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
const tabFolderWorkingData = new Map();
|
||||
|
||||
for (const folderData of data) {
|
||||
const workingData = {
|
||||
stateData: folderData,
|
||||
node: null,
|
||||
containingTabsFragment: document.createDocumentFragment(),
|
||||
};
|
||||
tabFolderWorkingData.set(folderData.id, workingData);
|
||||
try {
|
||||
const workingData = {
|
||||
stateData: folderData,
|
||||
node: null,
|
||||
containingTabsFragment: document.createDocumentFragment(),
|
||||
};
|
||||
tabFolderWorkingData.set(folderData.id, workingData);
|
||||
|
||||
const oldGroup = document.getElementById(folderData.id);
|
||||
folderData.emptyTabIds.forEach((id) => {
|
||||
oldGroup?.querySelector(`tab[id="${id}"]`)?.setAttribute("zen-empty-tab", true);
|
||||
});
|
||||
if (gBrowser.isTabGroup(oldGroup)) {
|
||||
if (!folderData.splitViewGroup) {
|
||||
const folder = this._createFolderNode({
|
||||
id: folderData.id,
|
||||
label: folderData.name,
|
||||
collapsed: folderData.collapsed,
|
||||
pinned: folderData.pinned,
|
||||
saveOnWindowClose: folderData.saveOnWindowClose,
|
||||
workspaceId: folderData.workspaceId,
|
||||
});
|
||||
folder.setAttribute("id", folderData.id);
|
||||
workingData.node = folder;
|
||||
oldGroup.before(folder);
|
||||
} else {
|
||||
workingData.node = oldGroup;
|
||||
}
|
||||
while (oldGroup.tabs.length) {
|
||||
const tab = oldGroup.tabs[0];
|
||||
if (folderData.workspaceId) {
|
||||
tab.setAttribute("zen-workspace-id", folderData.workspaceId);
|
||||
const oldGroup = document.getElementById(folderData.id);
|
||||
folderData.emptyTabIds.forEach((id) => {
|
||||
oldGroup?.querySelector(`tab[id="${id}"]`)?.setAttribute("zen-empty-tab", true);
|
||||
});
|
||||
if (gBrowser.isTabGroup(oldGroup)) {
|
||||
if (!folderData.splitViewGroup) {
|
||||
const folder = this._createFolderNode({
|
||||
id: folderData.id,
|
||||
label: folderData.name,
|
||||
collapsed: folderData.collapsed,
|
||||
pinned: folderData.pinned,
|
||||
saveOnWindowClose: folderData.saveOnWindowClose,
|
||||
workspaceId: folderData.workspaceId,
|
||||
});
|
||||
folder.setAttribute("id", folderData.id);
|
||||
workingData.node = folder;
|
||||
oldGroup.before(folder);
|
||||
} else {
|
||||
workingData.node = oldGroup;
|
||||
}
|
||||
while (oldGroup.tabs.length) {
|
||||
const tab = oldGroup.tabs[0];
|
||||
if (folderData.workspaceId) {
|
||||
tab.setAttribute("zen-workspace-id", folderData.workspaceId);
|
||||
}
|
||||
workingData.containingTabsFragment.appendChild(tab);
|
||||
}
|
||||
if (!folderData.splitViewGroup) {
|
||||
oldGroup.remove();
|
||||
}
|
||||
workingData.containingTabsFragment.appendChild(tab);
|
||||
}
|
||||
if (!folderData.splitViewGroup) {
|
||||
oldGroup.remove();
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Error restoring Zen Folders session data:", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,5 +15,6 @@ DIRS += [
|
||||
"urlbar",
|
||||
"toolkit",
|
||||
"sessionstore",
|
||||
"space-routing",
|
||||
"share",
|
||||
]
|
||||
|
||||
@@ -10,7 +10,9 @@ const lazy = {};
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
|
||||
SessionStore: "resource:///modules/sessionstore/SessionStore.sys.mjs",
|
||||
SessionStartup: "resource:///modules/sessionstore/SessionStartup.sys.mjs",
|
||||
gWindowSyncEnabled: "resource:///modules/zen/ZenWindowSync.sys.mjs",
|
||||
gSyncOnlyPinnedTabs: "resource:///modules/zen/ZenWindowSync.sys.mjs",
|
||||
DeferredTask: "resource://gre/modules/DeferredTask.sys.mjs",
|
||||
});
|
||||
|
||||
@@ -51,6 +53,9 @@ class nsZenSidebarObject {
|
||||
}
|
||||
|
||||
set data(data) {
|
||||
if (typeof data !== "object") {
|
||||
throw new Error("Sidebar data must be an object");
|
||||
}
|
||||
this.#sidebar = data;
|
||||
}
|
||||
}
|
||||
@@ -151,6 +156,34 @@ export class nsZenSessionManager {
|
||||
folderIcon: row.getResultByName("folder_icon"),
|
||||
isFolderCollapsed: Boolean(row.getResultByName("is_folder_collapsed")),
|
||||
}));
|
||||
try {
|
||||
data.recoveryData = await IOUtils.readJSON(
|
||||
PathUtils.join(
|
||||
Services.dirsvc.get("ProfD", Ci.nsIFile).path,
|
||||
"sessionstore-backups",
|
||||
"recovery.jsonlz4"
|
||||
),
|
||||
{ decompress: true }
|
||||
);
|
||||
this.log("Recovered recovery data from sessionstore-backups");
|
||||
} catch {
|
||||
/* ignore errors reading recovery data */
|
||||
}
|
||||
if (!data.recoverYData) {
|
||||
try {
|
||||
data.recoveryData = await IOUtils.readJSON(
|
||||
PathUtils.join(
|
||||
Services.dirsvc.get("ProfD", Ci.nsIFile).path,
|
||||
"sessionstore-backups",
|
||||
"recovery.jsonlz4"
|
||||
),
|
||||
{ decompress: true }
|
||||
);
|
||||
this.log("Recovered recovery data from sessionstore-backups");
|
||||
} catch {
|
||||
/* ignore errors reading recovery data */
|
||||
}
|
||||
}
|
||||
this._migrationData = data;
|
||||
} catch {
|
||||
/* ignore errors during migration */
|
||||
@@ -199,6 +232,13 @@ export class nsZenSessionManager {
|
||||
);
|
||||
}
|
||||
|
||||
get #shouldRestoreFromCrash() {
|
||||
return (
|
||||
lazy.SessionStartup.previousSessionCrashed &&
|
||||
Services.prefs.getBoolPref("browser.sessionstore.resume_from_crash")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the session file is read. Restores the sidebar data
|
||||
* into all windows.
|
||||
@@ -238,9 +278,22 @@ export class nsZenSessionManager {
|
||||
},
|
||||
];
|
||||
}
|
||||
return initialState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after @onFileRead, when session startup has crash checkpoint information available.
|
||||
* Restores the sidebar data into all windows, and runs any crash checkpoint related logic,
|
||||
* such as restoring only pinned tabs if the previous session was not crashed and the user
|
||||
* preference is set to do so.
|
||||
*
|
||||
* @param {object} initialState
|
||||
* The initial session state read from the session file, possibly modified by onFileRead.
|
||||
*/
|
||||
onCrashCheckpoints(initialState) {
|
||||
// When we don't have browser.startup.page set to resume session,
|
||||
// we only want to restore the pinned tabs into the new windows.
|
||||
if (this.#shouldRestoreOnlyPinned && this.#sidebar?.tabs) {
|
||||
if (this.#shouldRestoreOnlyPinned && !this.#shouldRestoreFromCrash && this.#sidebar?.tabs) {
|
||||
this.log("Restoring only pinned tabs into windows");
|
||||
const sidebar = this.#sidebar;
|
||||
sidebar.tabs = (sidebar.tabs || []).filter((tab) => tab.pinned);
|
||||
@@ -272,7 +325,6 @@ export class nsZenSessionManager {
|
||||
this.saveState(Cu.cloneInto(initialState, {}));
|
||||
}
|
||||
delete this._shouldRunMigration;
|
||||
return initialState;
|
||||
}
|
||||
|
||||
get #sidebar() {
|
||||
@@ -298,6 +350,11 @@ export class nsZenSessionManager {
|
||||
initialState?.lastSessionState,
|
||||
this._migrationData
|
||||
);
|
||||
if (!initialState?.windows?.length && this._migrationData?.recoveryData) {
|
||||
this.log("Using recovery data for migration");
|
||||
initialState = this._migrationData.recoveryData;
|
||||
}
|
||||
delete this._migrationData?.recoveryData;
|
||||
// Restore spaces into the sidebar object if we don't
|
||||
// have any yet.
|
||||
if (!this.#sidebar.spaces?.length) {
|
||||
@@ -350,6 +407,25 @@ export class nsZenSessionManager {
|
||||
return initialState;
|
||||
}
|
||||
|
||||
onRestoringClosedWindow(aWinData) {
|
||||
// We only want to save all pinned tabs if the user preference allows it.
|
||||
// See https://github.com/zen-browser/desktop/issues/12307
|
||||
if (this.#shouldRestoreOnlyPinned && aWinData?.tabs?.length) {
|
||||
this.log("Restoring only pinned tabs for closed window");
|
||||
this.#filterUnpinnedTabs(aWinData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters out all unpinned tabs and groups from the given window data object.
|
||||
*
|
||||
* @param {object} aWindow - The window data object to filter.
|
||||
*/
|
||||
#filterUnpinnedTabs(aWindow) {
|
||||
aWindow.tabs = aWindow.tabs.filter((tab) => tab.pinned);
|
||||
aWindow.groups = aWindow.groups?.filter((group) => group.pinned);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a given window data object is saveable.
|
||||
*
|
||||
@@ -376,10 +452,11 @@ export class nsZenSessionManager {
|
||||
this.#collectWindowData(windows);
|
||||
// This would save the data to disk asynchronously or when
|
||||
// quitting the app.
|
||||
this.#file.data = this.#sidebar;
|
||||
let sidebar = this.#sidebar;
|
||||
this.#file.data = sidebar;
|
||||
this.#file.saveSoon();
|
||||
this.#debounceRegeneration();
|
||||
this.log(`Saving Zen session data with ${this.#sidebar.tabs?.length || 0} tabs`);
|
||||
this.log(`Saving Zen session data with ${sidebar.tabs?.length || 0} tabs`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -480,6 +557,13 @@ export class nsZenSessionManager {
|
||||
this.#sidebar = sidebarData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters out tabs that are not useful to restore, such as empty tabs with no group association.
|
||||
* If removeUnpinnedTabs is true, it also filters out unpinned tabs.
|
||||
*
|
||||
* @param {Array} tabs - The array of tab data objects to filter.
|
||||
* @returns {Array} The filtered array of tab data objects.
|
||||
*/
|
||||
#filterUnusedTabs(tabs) {
|
||||
return tabs.filter((tab) => {
|
||||
// We need to ignore empty tabs with no group association
|
||||
@@ -529,10 +613,34 @@ export class nsZenSessionManager {
|
||||
if (!sidebar) {
|
||||
return;
|
||||
}
|
||||
aWindowData.tabs = sidebar.tabs || [];
|
||||
aWindowData.splitViewData = sidebar.splitViewData;
|
||||
// If we should only sync the pinned tabs, we should only edit the unpinned
|
||||
// tabs in the window data and keep the pinned tabs from the window data,
|
||||
// as they should be the same as the ones in the sidebar.
|
||||
if (lazy.gSyncOnlyPinnedTabs) {
|
||||
let pinnedTabs = (sidebar.tabs || []).filter((tab) => tab.pinned);
|
||||
let unpinedWindowTabs = [];
|
||||
if (!this.#shouldRestoreOnlyPinned) {
|
||||
unpinedWindowTabs = (aWindowData.tabs || []).filter((tab) => !tab.pinned);
|
||||
}
|
||||
aWindowData.tabs = [...pinnedTabs, ...unpinedWindowTabs];
|
||||
|
||||
// We restore ALL the split view data in the sidebar, if the group doesn't exist in the window,
|
||||
// it should be a no-op anyways.
|
||||
aWindowData.splitViewData = [
|
||||
...(sidebar.splitViewData || []),
|
||||
...(aWindowData.splitViewData || []),
|
||||
];
|
||||
// Same thing with groups, we restore all the groups from the sidebar, if they don't have any
|
||||
// existing tabs in the window, they should be a no-op.
|
||||
aWindowData.groups = [...(sidebar.groups || []), ...(aWindowData.groups || [])];
|
||||
} else {
|
||||
aWindowData.tabs = sidebar.tabs || [];
|
||||
aWindowData.splitViewData = sidebar.splitViewData;
|
||||
aWindowData.groups = sidebar.groups;
|
||||
}
|
||||
|
||||
// Folders are always pinned, so we dont need to check for the pinned state here.
|
||||
aWindowData.folders = sidebar.folders;
|
||||
aWindowData.groups = sidebar.groups;
|
||||
aWindowData.spaces = sidebar.spaces;
|
||||
}
|
||||
|
||||
@@ -558,17 +666,19 @@ export class nsZenSessionManager {
|
||||
);
|
||||
let windowToClone = windows[0] || {};
|
||||
let newWindow = Cu.cloneInto(windowToClone, {});
|
||||
let shouldRestoreOnlyPinned = !lazy.gWindowSyncEnabled || lazy.gSyncOnlyPinnedTabs;
|
||||
if (windows.length < 2) {
|
||||
// We only want to restore the sidebar object if we found
|
||||
// only one normal window to clone from (which is the one
|
||||
// we are opening).
|
||||
this.log("Restoring sidebar data into new window");
|
||||
this.#restoreWindowData(newWindow);
|
||||
shouldRestoreOnlyPinned ||= this.#shouldRestoreOnlyPinned;
|
||||
}
|
||||
newWindow.tabs = this.#filterUnusedTabs(newWindow.tabs || []);
|
||||
if (!lazy.gWindowSyncEnabled) {
|
||||
// Don't bring over any unpinned tabs if window sync is disabled.
|
||||
newWindow.tabs = newWindow.tabs.filter((tab) => tab.pinned);
|
||||
if (shouldRestoreOnlyPinned) {
|
||||
// Don't bring over any unpinned tabs if window sync is disabled or if syncing only pinned tabs.
|
||||
this.#filterUnpinnedTabs(newWindow);
|
||||
}
|
||||
|
||||
// These are window-specific from the previous window state that
|
||||
|
||||
@@ -15,9 +15,16 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
ZenSessionStore: "resource:///modules/zen/ZenSessionManager.sys.mjs",
|
||||
TabStateCache: "resource:///modules/sessionstore/TabStateCache.sys.mjs",
|
||||
setTimeout: "resource://gre/modules/Timer.sys.mjs",
|
||||
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(lazy, "gWindowSyncEnabled", "zen.window-sync.enabled", true);
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
lazy,
|
||||
"gSyncOnlyPinnedTabs",
|
||||
"zen.window-sync.sync-only-pinned-tabs",
|
||||
true
|
||||
);
|
||||
XPCOMUtils.defineLazyPreferenceGetter(lazy, "gShouldLog", "zen.window-sync.log", true);
|
||||
|
||||
const OBSERVING = ["browser-window-before-show", "sessionstore-windows-restored"];
|
||||
@@ -189,6 +196,10 @@ class nsZenWindowSync {
|
||||
// to avoid confusing the old private window behavior.
|
||||
let forcedSync = !aWindow.gZenWorkspaces?.privateWindowOrDisabled;
|
||||
let hasUnsyncedArg = false;
|
||||
// See issue https://github.com/zen-browser/desktop/issues/12211
|
||||
if (lazy.PrivateBrowsingUtils.isWindowPrivate(aWindow)) {
|
||||
aWindow._zenStartupSyncFlag = "synced";
|
||||
}
|
||||
if (aWindow._zenStartupSyncFlag === "synced") {
|
||||
forcedSync = true;
|
||||
} else if (aWindow._zenStartupSyncFlag === "unsynced") {
|
||||
@@ -236,6 +247,9 @@ class nsZenWindowSync {
|
||||
if (tab.pinned && !tab._zenPinnedInitialState) {
|
||||
await this.setPinnedTabState(tab);
|
||||
}
|
||||
if (!lazy.gWindowSyncEnabled || (lazy.gSyncOnlyPinnedTabs && !tab.pinned)) {
|
||||
tab._zenContentsVisible = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -313,7 +327,7 @@ class nsZenWindowSync {
|
||||
return;
|
||||
}
|
||||
if (INSTANT_EVENTS.includes(aEvent.type)) {
|
||||
this.#handleNextEvent(aEvent);
|
||||
this.#handleNextEventInternal(aEvent);
|
||||
return;
|
||||
}
|
||||
if (this.#eventHandlingContext.window && this.#eventHandlingContext.window !== window) {
|
||||
@@ -360,30 +374,31 @@ class nsZenWindowSync {
|
||||
this.#syncHandlers.delete(aHandler);
|
||||
}
|
||||
|
||||
#handleNextEventInternal(aEvent) {
|
||||
const handler = `on_${aEvent.type}`;
|
||||
if (typeof this[handler] !== "function") {
|
||||
throw new Error(`No handler for event type: ${aEvent.type}`);
|
||||
}
|
||||
return this[handler](aEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the next event by calling the appropriate handler method.
|
||||
*
|
||||
* @param {Event} aEvent - The event to handle.
|
||||
*/
|
||||
#handleNextEvent(aEvent) {
|
||||
const handler = `on_${aEvent.type}`;
|
||||
async #handleNextEvent(aEvent) {
|
||||
try {
|
||||
if (typeof this[handler] === "function") {
|
||||
let promise = this[handler](aEvent) || Promise.resolve();
|
||||
promise.then(() => {
|
||||
for (let syncHandler of this.#syncHandlers) {
|
||||
try {
|
||||
syncHandler(aEvent);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
throw new Error(`No handler for event type: ${aEvent.type}`);
|
||||
await this.#handleNextEventInternal(aEvent);
|
||||
} catch (e) {
|
||||
return Promise.reject(e);
|
||||
console.error(e);
|
||||
}
|
||||
for (let syncHandler of this.#syncHandlers) {
|
||||
try {
|
||||
syncHandler(aEvent);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -776,39 +791,41 @@ class nsZenWindowSync {
|
||||
#styleSwapedBrowsers(aOurTab, aOtherTab, callback = undefined, promiseToWait = null) {
|
||||
const ourBrowser = aOurTab.linkedBrowser;
|
||||
const otherBrowser = aOtherTab.linkedBrowser;
|
||||
return new Promise((resolve) => {
|
||||
aOurTab.ownerGlobal.requestAnimationFrame(async () => {
|
||||
if (callback) {
|
||||
const browserBlob = await aOtherTab.ownerGlobal.PageThumbs.captureToBlob(
|
||||
aOtherTab.linkedBrowser,
|
||||
{
|
||||
fullScale: true,
|
||||
fullViewport: true,
|
||||
}
|
||||
);
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
return new Promise(async (resolve) => {
|
||||
if (callback) {
|
||||
const browserBlob = await aOtherTab.ownerGlobal.PageThumbs.captureToBlob(
|
||||
aOtherTab.linkedBrowser,
|
||||
{
|
||||
fullScale: true,
|
||||
fullViewport: true,
|
||||
}
|
||||
);
|
||||
|
||||
let mySrc = await new Promise((r, re) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(browserBlob);
|
||||
reader.onloadend = function () {
|
||||
// result includes identifier 'data:image/png;base64,' plus the base64 data
|
||||
r(reader.result);
|
||||
};
|
||||
reader.onerror = function () {
|
||||
re(new Error("Failed to read blob as data URL"));
|
||||
};
|
||||
});
|
||||
|
||||
this.#createPseudoImageForBrowser(otherBrowser, mySrc);
|
||||
otherBrowser.setAttribute("zen-pseudo-hidden", "true");
|
||||
await promiseToWait;
|
||||
callback();
|
||||
}
|
||||
let mySrc = await new Promise((r, re) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(browserBlob);
|
||||
reader.onloadend = function () {
|
||||
// result includes identifier 'data:image/png;base64,' plus the base64 data
|
||||
r(reader.result);
|
||||
};
|
||||
reader.onerror = function () {
|
||||
re(new Error("Failed to read blob as data URL"));
|
||||
};
|
||||
});
|
||||
|
||||
await promiseToWait;
|
||||
this.#createPseudoImageForBrowser(otherBrowser, mySrc);
|
||||
this.#maybeRemovePseudoImageForBrowser(ourBrowser);
|
||||
ourBrowser.removeAttribute("zen-pseudo-hidden");
|
||||
resolve();
|
||||
});
|
||||
otherBrowser.setAttribute("zen-pseudo-hidden", "true");
|
||||
callback();
|
||||
} else {
|
||||
this.#maybeRemovePseudoImageForBrowser(ourBrowser);
|
||||
ourBrowser.removeAttribute("zen-pseudo-hidden");
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -910,7 +927,9 @@ class nsZenWindowSync {
|
||||
// Ignore previous tabs that are still "active". These scenarios could happen for example,
|
||||
// when selecting on a split view tab that was already active.
|
||||
if (aPreviousTab?._zenContentsVisible && !activeTabs.includes(aPreviousTab)) {
|
||||
let tabsToSwap = aPreviousTab.splitView ? aPreviousTab.group.tabs : [aPreviousTab];
|
||||
let tabsToSwap = aPreviousTab.group?.hasAttribute("split-view-group")
|
||||
? aPreviousTab.group.tabs
|
||||
: [aPreviousTab];
|
||||
for (const tab of tabsToSwap) {
|
||||
const otherTabToShow = this.#getActiveTabFromOtherWindows(aWindow, tab.id, (t) =>
|
||||
t?.splitView ? t.group.tabs.some((st) => st.selected) : t?.selected
|
||||
@@ -945,6 +964,9 @@ class nsZenWindowSync {
|
||||
*/
|
||||
#delegateGenericSyncEvent(aEvent, flags = 0) {
|
||||
const item = aEvent.target;
|
||||
if (lazy.gSyncOnlyPinnedTabs && !item.pinned) {
|
||||
return;
|
||||
}
|
||||
this.#syncItemForAllWindows(item, flags);
|
||||
}
|
||||
|
||||
@@ -1081,16 +1103,19 @@ class nsZenWindowSync {
|
||||
|
||||
/* Mark: Event Handlers */
|
||||
|
||||
on_TabOpen(aEvent) {
|
||||
on_TabOpen(aEvent, { duringPinning = false } = {}) {
|
||||
const tab = aEvent.target;
|
||||
const window = tab.ownerGlobal;
|
||||
const isUnsyncedWindow = window.gZenWorkspaces.privateWindowOrDisabled;
|
||||
if (tab.id) {
|
||||
if (tab.id && !duringPinning) {
|
||||
// This tab was opened as part of a sync operation.
|
||||
return;
|
||||
}
|
||||
tab._zenContentsVisible = true;
|
||||
tab.id = this.#newTabSyncId;
|
||||
if (lazy.gSyncOnlyPinnedTabs && !tab.pinned) {
|
||||
return;
|
||||
}
|
||||
if (isUnsyncedWindow || !lazy.gWindowSyncEnabled) {
|
||||
return;
|
||||
}
|
||||
@@ -1108,6 +1133,9 @@ class nsZenWindowSync {
|
||||
SYNC_FLAG_ICON | SYNC_FLAG_LABEL | SYNC_FLAG_MOVE
|
||||
);
|
||||
});
|
||||
if (duringPinning && tab?.splitView) {
|
||||
this.on_ZenSplitViewTabsSplit({ target: tab.group });
|
||||
}
|
||||
this.#maybeFlushTabState(tab);
|
||||
}
|
||||
|
||||
@@ -1129,7 +1157,8 @@ class nsZenWindowSync {
|
||||
}
|
||||
|
||||
on_TabMove(aEvent) {
|
||||
return this.#delegateGenericSyncEvent(aEvent, SYNC_FLAG_MOVE);
|
||||
this.#delegateGenericSyncEvent(aEvent, SYNC_FLAG_MOVE);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
on_TabPinned(aEvent) {
|
||||
@@ -1141,7 +1170,14 @@ class nsZenWindowSync {
|
||||
if (!tab._zenPinnedInitialState) {
|
||||
tabStatePromise = this.setPinnedTabState(tab);
|
||||
}
|
||||
return Promise.all([tabStatePromise, this.on_TabMove(aEvent)]);
|
||||
return Promise.all([
|
||||
tabStatePromise,
|
||||
this.on_TabMove(aEvent).then(() => {
|
||||
if (lazy.gSyncOnlyPinnedTabs) {
|
||||
this.on_TabOpen({ target: tab }, { duringPinning: true });
|
||||
}
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
on_TabUnpinned(aEvent) {
|
||||
@@ -1152,7 +1188,11 @@ class nsZenWindowSync {
|
||||
delete targetTab._zenPinnedInitialState;
|
||||
}
|
||||
});
|
||||
return this.on_TabMove(aEvent);
|
||||
return this.on_TabMove(aEvent).then(() => {
|
||||
if (lazy.gSyncOnlyPinnedTabs) {
|
||||
this.on_TabClose({ target: tab });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
on_TabAddedToEssentials(aEvent) {
|
||||
@@ -1343,4 +1383,6 @@ class nsZenWindowSync {
|
||||
|
||||
// eslint-disable-next-line mozilla/valid-lazy
|
||||
export const gWindowSyncEnabled = lazy.gWindowSyncEnabled;
|
||||
// eslint-disable-next-line mozilla/valid-lazy
|
||||
export const gSyncOnlyPinnedTabs = lazy.gSyncOnlyPinnedTabs;
|
||||
export const ZenWindowSync = new nsZenWindowSync();
|
||||
|
||||
17
src/zen/space-routing/ZenSpaceRouting.sys.mjs
Normal file
17
src/zen/space-routing/ZenSpaceRouting.sys.mjs
Normal file
@@ -0,0 +1,17 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import { JSONFile } from "resource://gre/modules/JSONFile.sys.mjs";
|
||||
|
||||
class nsZenSpaceRouting {
|
||||
#jsonFile = null;
|
||||
|
||||
constructor() {
|
||||
this.#jsonFile = new JSONFile({
|
||||
path: PathUtils.join(PathUtils.profileDir, "space-routing.json"),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export var ZenSpaceRouting = new nsZenSpaceRouting();
|
||||
7
src/zen/space-routing/moz.build
Normal file
7
src/zen/space-routing/moz.build
Normal file
@@ -0,0 +1,7 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXTRA_JS_MODULES.zen += [
|
||||
"ZenSpaceRouting.sys.mjs",
|
||||
]
|
||||
@@ -208,6 +208,10 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
if (typeof groupIndex === "undefined") {
|
||||
groupIndex = this._data.findIndex((group) => group.tabs.includes(tab));
|
||||
}
|
||||
// If groupIndex === -1, so `this._data.findIndex` couldn't find the split group
|
||||
if (groupIndex < 0) {
|
||||
return;
|
||||
}
|
||||
const group = this._data[groupIndex];
|
||||
const tabIndex = group.tabs.indexOf(tab);
|
||||
group.tabs.splice(tabIndex, 1);
|
||||
@@ -259,6 +263,33 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
return element;
|
||||
}
|
||||
|
||||
_calculateDropSide(event, panelsRect) {
|
||||
const { width, height } = panelsRect;
|
||||
const { clientX, clientY } = event;
|
||||
// TODO(octaviusz): Maybe we should add this as preference
|
||||
// `zen.splitView.tab-drop-treshold`
|
||||
const quarterWidth = width / 4;
|
||||
const quarterHeight = height / 4;
|
||||
|
||||
const edges = [
|
||||
{ side: "left", dist: clientX - panelsRect.left, threshold: quarterWidth },
|
||||
{ side: "right", dist: panelsRect.right - clientX, threshold: quarterWidth },
|
||||
{ side: "top", dist: clientY - panelsRect.top, threshold: quarterHeight },
|
||||
{ side: "bottom", dist: panelsRect.bottom - clientY, threshold: quarterHeight },
|
||||
];
|
||||
|
||||
let closestEdge = null;
|
||||
let minDist = Infinity;
|
||||
for (const edge of edges) {
|
||||
if (edge.dist < edge.threshold && edge.dist < minDist) {
|
||||
minDist = edge.dist;
|
||||
closestEdge = edge;
|
||||
}
|
||||
}
|
||||
|
||||
return closestEdge ? closestEdge.side : null;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line complexity
|
||||
onBrowserDragOverToSplit(event) {
|
||||
gBrowser.tabContainer.tabDragAndDrop.clearSpaceSwitchTimer();
|
||||
@@ -303,6 +334,7 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
const panelsRect = gBrowser.tabbox.getBoundingClientRect();
|
||||
const panelsWidth = panelsRect.width;
|
||||
const panelsHeight = panelsRect.height;
|
||||
if (
|
||||
event.clientX > panelsRect.left + panelsWidth - 10 ||
|
||||
event.clientX < panelsRect.left + 10 ||
|
||||
@@ -311,11 +343,17 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const dropSide = this._calculateDropSide(event, panelsRect);
|
||||
if (!dropSide) {
|
||||
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
|
||||
event.clientX > panelsRect.left + (panelsWidth / 4) * 3 ||
|
||||
event.clientY < panelsRect.top + panelsHeight / 4 ||
|
||||
event.clientY > panelsRect.top + (panelsHeight / 4) * 3
|
||||
)
|
||||
) {
|
||||
return;
|
||||
@@ -336,93 +374,113 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
this._canDrop = true;
|
||||
// eslint-disable-next-line mozilla/valid-services
|
||||
Services.zen.playHapticFeedback();
|
||||
{
|
||||
this._draggingTab = draggedTab;
|
||||
gBrowser.selectedTab = oldTab;
|
||||
this._hasAnimated = true;
|
||||
this.tabBrowserPanel.setAttribute("dragging-split", "true");
|
||||
// Add a min width to all the browser elements to prevent them from resizing
|
||||
// eslint-disable-next-line no-shadow
|
||||
const panelsWidth = gBrowser.tabbox.getBoundingClientRect().width;
|
||||
let numOfTabsToDivide = 2;
|
||||
if (currentView) {
|
||||
numOfTabsToDivide = currentView.tabs.length + 1;
|
||||
this._draggingTab = draggedTab;
|
||||
gBrowser.selectedTab = oldTab;
|
||||
this._hasAnimated = true;
|
||||
this.tabBrowserPanel.setAttribute("dragging-split", "true");
|
||||
this._animateDropEdge(dropSide, currentView, draggedTab, oldTab);
|
||||
}
|
||||
|
||||
_animateDropEdge(dropSide, currentView, draggedTab, oldTab) {
|
||||
// Add a min width to all the browser elements to prevent them from resizing
|
||||
// eslint-disable-next-line no-shadow
|
||||
const { height, width } = gBrowser.tabbox.getBoundingClientRect();
|
||||
let numOfTabsToDivide = 2;
|
||||
if (currentView) {
|
||||
numOfTabsToDivide = currentView.tabs.length + 1;
|
||||
}
|
||||
const halfWidth = width / numOfTabsToDivide;
|
||||
const halfHeight = height / numOfTabsToDivide;
|
||||
const side = dropSide;
|
||||
for (const browser of gBrowser.browsers) {
|
||||
if (!browser) {
|
||||
continue;
|
||||
}
|
||||
const halfWidth = panelsWidth / numOfTabsToDivide;
|
||||
let threshold =
|
||||
gNavToolbox.getBoundingClientRect().width *
|
||||
(gZenVerticalTabsManager._prefsRightSide ? 0 : 1);
|
||||
if (gZenCompactModeManager.preference) {
|
||||
threshold = 0;
|
||||
const { width: browserWidth, height: browserHeight } = browser.getBoundingClientRect();
|
||||
// Only apply it to the left side because if we add it to the right side,
|
||||
// we wont be able to move the element to the left.
|
||||
// FIXME: This is a workaround, we should find a better way to do this
|
||||
switch (side) {
|
||||
case "left":
|
||||
browser.style.minWidth = `${browserWidth}px`;
|
||||
break;
|
||||
case "top":
|
||||
browser.style.minHeight = `${browserHeight}px`;
|
||||
break;
|
||||
}
|
||||
const side = event.clientX - threshold > halfWidth ? "right" : "left";
|
||||
for (const browser of gBrowser.browsers) {
|
||||
if (!browser) {
|
||||
continue;
|
||||
}
|
||||
this.fakeBrowser = document.createXULElement("vbox");
|
||||
window.addEventListener("dragend", this.onBrowserDragEndToSplit, { once: true });
|
||||
const padding = ZenThemeModifier.elementSeparation;
|
||||
this.fakeBrowser.setAttribute("flex", "1");
|
||||
this.fakeBrowser.id = "zen-split-view-fake-browser";
|
||||
if (oldTab.splitView) {
|
||||
this.fakeBrowser.setAttribute("has-split-view", "true");
|
||||
}
|
||||
gBrowser.tabbox.appendChild(this.fakeBrowser);
|
||||
this.fakeBrowser.setAttribute("side", side);
|
||||
let animateTabBox = null;
|
||||
let animateFakeBrowser = null;
|
||||
switch (side) {
|
||||
case "left":
|
||||
animateTabBox = {
|
||||
padding: [0, `0 0 0 ${halfWidth}px`],
|
||||
};
|
||||
animateFakeBrowser = {
|
||||
width: [0, `${halfWidth - padding}px`],
|
||||
margin: [0, `0 0 0 ${-halfWidth}px`],
|
||||
};
|
||||
break;
|
||||
case "right":
|
||||
animateTabBox = {
|
||||
padding: [0, `0 ${halfWidth}px 0 0`],
|
||||
};
|
||||
animateFakeBrowser = {
|
||||
width: [0, `${halfWidth - padding}px`],
|
||||
};
|
||||
break;
|
||||
|
||||
case "top":
|
||||
animateTabBox = {
|
||||
padding: [0, `${halfHeight}px 0 0 0`],
|
||||
};
|
||||
animateFakeBrowser = {
|
||||
height: [0, `${halfHeight - padding}px`],
|
||||
margin: [0, `${-halfHeight}px 0 0 0`],
|
||||
};
|
||||
break;
|
||||
|
||||
case "bottom":
|
||||
animateTabBox = {
|
||||
padding: [0, `0 0 ${halfHeight}px 0`],
|
||||
};
|
||||
animateFakeBrowser = {
|
||||
height: [0, `${halfHeight - padding}px`],
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
this._finishAllAnimatingPromise = Promise.all([
|
||||
gZenUIManager.motion.animate(gBrowser.tabbox, animateTabBox, {
|
||||
duration: 0.1,
|
||||
easing: "ease-out",
|
||||
}),
|
||||
gZenUIManager.motion.animate(this.fakeBrowser, animateFakeBrowser, {
|
||||
duration: 0.1,
|
||||
easing: "ease-out",
|
||||
}),
|
||||
]);
|
||||
if (this._finishAllAnimatingPromise) {
|
||||
this._finishAllAnimatingPromise.then(() => {
|
||||
if (draggedTab !== oldTab) {
|
||||
draggedTab.linkedBrowser.docShellIsActive = false;
|
||||
draggedTab.linkedBrowser
|
||||
.closest(".browserSidebarContainer")
|
||||
.classList.remove("deck-selected");
|
||||
}
|
||||
const width = browser.getBoundingClientRect().width;
|
||||
// Only apply it to the left side because if we add it to the right side,
|
||||
// we wont be able to move the element to the left.
|
||||
// FIXME: This is a workaround, we should find a better way to do this
|
||||
if (side === "left") {
|
||||
browser.style.minWidth = `${width}px`;
|
||||
}
|
||||
}
|
||||
this.fakeBrowser = document.createXULElement("vbox");
|
||||
window.addEventListener("dragend", this.onBrowserDragEndToSplit, { once: true });
|
||||
const padding = ZenThemeModifier.elementSeparation;
|
||||
this.fakeBrowser.setAttribute("flex", "1");
|
||||
this.fakeBrowser.id = "zen-split-view-fake-browser";
|
||||
if (oldTab.splitView) {
|
||||
this.fakeBrowser.setAttribute("has-split-view", "true");
|
||||
}
|
||||
gBrowser.tabbox.appendChild(this.fakeBrowser);
|
||||
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,
|
||||
},
|
||||
{
|
||||
duration: 0.1,
|
||||
easing: "ease-out",
|
||||
}
|
||||
),
|
||||
gZenUIManager.motion.animate(
|
||||
this.fakeBrowser,
|
||||
{
|
||||
width: [0, `${halfWidth - padding}px`],
|
||||
...(side === "left"
|
||||
? {
|
||||
marginLeft: [0, `${-halfWidth}px`],
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
{
|
||||
duration: 0.1,
|
||||
easing: "ease-out",
|
||||
}
|
||||
),
|
||||
]);
|
||||
if (this._finishAllAnimatingPromise) {
|
||||
this._finishAllAnimatingPromise.then(() => {
|
||||
if (draggedTab !== oldTab) {
|
||||
draggedTab.linkedBrowser.docShellIsActive = false;
|
||||
draggedTab.linkedBrowser
|
||||
.closest(".browserSidebarContainer")
|
||||
.classList.remove("deck-selected");
|
||||
}
|
||||
this.fakeBrowser.addEventListener("dragleave", this.onBrowserDragEndToSplit);
|
||||
this._canDrop = true;
|
||||
});
|
||||
}
|
||||
this.fakeBrowser.addEventListener("dragleave", this.onBrowserDragEndToSplit);
|
||||
this._canDrop = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -447,12 +505,14 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
return;
|
||||
}
|
||||
const panelsWidth = panelsRect.width;
|
||||
const panelsHeight = panelsRect.height;
|
||||
let numOfTabsToDivide = 2;
|
||||
const currentView = this._data[this._lastOpenedTab.splitViewValue];
|
||||
if (currentView) {
|
||||
numOfTabsToDivide = currentView.tabs.length + 1;
|
||||
}
|
||||
const halfWidth = panelsWidth / numOfTabsToDivide;
|
||||
const halfHeight = panelsHeight / numOfTabsToDivide;
|
||||
const padding = ZenThemeModifier.elementSeparation;
|
||||
if (!this.fakeBrowser) {
|
||||
return;
|
||||
@@ -464,39 +524,60 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
...gBrowser.tabContainer.tabDragAndDrop.originalDragImageArgs
|
||||
);
|
||||
this._canDrop = false;
|
||||
Promise.all([
|
||||
gZenUIManager.motion.animate(
|
||||
gBrowser.tabbox,
|
||||
side === "left"
|
||||
? {
|
||||
paddingLeft: [`${halfWidth}px`, 0],
|
||||
}
|
||||
: {
|
||||
paddingRight: [`${halfWidth}px`, 0],
|
||||
},
|
||||
{
|
||||
duration: 0.1,
|
||||
easing: "ease-out",
|
||||
}
|
||||
),
|
||||
gZenUIManager.motion.animate(
|
||||
this.fakeBrowser,
|
||||
{
|
||||
width: [`${halfWidth - padding * 2}px`, 0],
|
||||
...(side === "left"
|
||||
? {
|
||||
marginLeft: [`${-halfWidth}px`, 0],
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
{
|
||||
duration: 0.1,
|
||||
easing: "ease-out",
|
||||
}
|
||||
),
|
||||
]).finally(() => {
|
||||
this._maybeRemoveFakeBrowser();
|
||||
});
|
||||
let animateTabBox = null;
|
||||
let animateFakeBrowser = null;
|
||||
switch (side) {
|
||||
case "left":
|
||||
animateTabBox = {
|
||||
padding: [`0 0 0 ${halfWidth}px`, 0],
|
||||
};
|
||||
animateFakeBrowser = {
|
||||
width: [`${halfWidth - padding}px`, 0],
|
||||
margin: [`0 0 0 ${-halfWidth}px`, 0],
|
||||
};
|
||||
break;
|
||||
case "right":
|
||||
animateTabBox = {
|
||||
padding: [`0 ${halfWidth}px 0 0`, 0],
|
||||
};
|
||||
animateFakeBrowser = {
|
||||
width: [`${halfWidth - padding}px`, 0],
|
||||
};
|
||||
break;
|
||||
case "top":
|
||||
animateTabBox = {
|
||||
padding: [`${halfHeight}px 0 0 0`, 0],
|
||||
};
|
||||
animateFakeBrowser = {
|
||||
height: [`${halfHeight - padding}px`, 0],
|
||||
margin: [`${-halfHeight}px 0 0 0`, 0],
|
||||
};
|
||||
break;
|
||||
case "bottom":
|
||||
animateTabBox = {
|
||||
padding: [`0 0 ${halfHeight}px 0`, 0],
|
||||
};
|
||||
animateFakeBrowser = {
|
||||
height: [`${halfHeight - padding}px`, 0],
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
this._finishAllAnimatingPromise = Promise.all([
|
||||
gZenUIManager.motion.animate(gBrowser.tabbox, animateTabBox, {
|
||||
duration: 0.1,
|
||||
easing: "ease-out",
|
||||
}),
|
||||
gZenUIManager.motion.animate(this.fakeBrowser, animateFakeBrowser, {
|
||||
duration: 0.1,
|
||||
easing: "ease-out",
|
||||
}),
|
||||
]);
|
||||
if (this._finishAllAnimatingPromise) {
|
||||
this._finishAllAnimatingPromise.then(() => {
|
||||
this._maybeRemoveFakeBrowser();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1386,10 +1467,10 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
new nsSplitLeafNode(tabs[i], 50),
|
||||
new nsSplitLeafNode(tabs[i + 1], 50),
|
||||
];
|
||||
rootNode.addChild(columnNode);
|
||||
rootNode.addChild(columnNode, false);
|
||||
}
|
||||
if (tabs.length % 2 !== 0) {
|
||||
rootNode.addChild(new nsSplitLeafNode(tabs[tabs.length - 1], rowWidth));
|
||||
rootNode.addChild(new nsSplitLeafNode(tabs[tabs.length - 1], rowWidth), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1845,12 +1926,24 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
const dropSide = this.fakeBrowser?.getAttribute("side");
|
||||
const containerRect = this.fakeBrowser.getBoundingClientRect();
|
||||
const padding = ZenThemeModifier.elementSeparation;
|
||||
const dropTarget = document.elementFromPoint(
|
||||
dropSide === "left"
|
||||
? containerRect.left + containerRect.width + padding + 5
|
||||
: containerRect.left - padding - 5,
|
||||
event.clientY
|
||||
);
|
||||
let targetX = event.clientX;
|
||||
let targetY = event.clientY;
|
||||
switch (dropSide) {
|
||||
case "left":
|
||||
targetX = containerRect.left + containerRect.width + padding + 5;
|
||||
break;
|
||||
case "right":
|
||||
targetX = containerRect.left - padding - 5;
|
||||
break;
|
||||
case "top":
|
||||
targetY = containerRect.top + containerRect.height + padding + 5;
|
||||
break;
|
||||
case "bottom":
|
||||
targetY = containerRect.top - padding - 5;
|
||||
break;
|
||||
}
|
||||
|
||||
const dropTarget = document.elementFromPoint(targetX, targetY);
|
||||
const browser =
|
||||
dropTarget?.closest("browser") ??
|
||||
dropTarget?.closest(".browserSidebarContainer")?.querySelector("browser");
|
||||
@@ -1862,7 +1955,7 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
|
||||
let droppedOnTab = gZenGlanceManager.getTabOrGlanceParent(gBrowser.getTabForBrowser(browser));
|
||||
if (droppedOnTab === this._draggingTab) {
|
||||
this.createEmptySplit(dropSide == "right");
|
||||
this.createEmptySplit(dropSide);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1919,29 +2012,21 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const droppedOnSplitNode = this.getSplitNodeFromTab(droppedOnTab);
|
||||
const parentNode = droppedOnSplitNode.parent;
|
||||
|
||||
// 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 dropping on a side, wrap entire layout in a new split at the root level
|
||||
if (hoverSide !== "center") {
|
||||
const splitDirection = hoverSide === "left" || hoverSide === "right" ? "row" : "column";
|
||||
if (parentNode.direction !== splitDirection) {
|
||||
this.splitIntoNode(
|
||||
droppedOnSplitNode,
|
||||
new nsSplitLeafNode(draggedTab, 50),
|
||||
hoverSide,
|
||||
0.5
|
||||
);
|
||||
const rootNode = group.layoutTree;
|
||||
const prepend = hoverSide === "left" || hoverSide === "top";
|
||||
|
||||
if (rootNode.direction === splitDirection) {
|
||||
// Root has the same direction, add as a new child of the root
|
||||
this.addTabToSplit(draggedTab, rootNode, prepend);
|
||||
} else {
|
||||
this.addTabToSplit(
|
||||
draggedTab,
|
||||
parentNode,
|
||||
/* prepend = */ hoverSide === "left" || hoverSide === "top"
|
||||
);
|
||||
// Different direction, wrap root in a new split node
|
||||
this.splitIntoNode(rootNode, new nsSplitLeafNode(draggedTab, 50), hoverSide, 0.5);
|
||||
}
|
||||
} else {
|
||||
this.addTabToSplit(draggedTab, group.layoutTree);
|
||||
@@ -1951,13 +2036,14 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
} else {
|
||||
// Create new split view with layout based on drop position
|
||||
let gridType = "vsep";
|
||||
const gridType = dropSide === "top" || dropSide === "bottom" ? "hsep" : "vsep";
|
||||
const topOrLeft = dropSide === "top" || dropSide === "left";
|
||||
|
||||
// Put tabs always as if it was dropped from the left
|
||||
this.splitTabs(
|
||||
dropSide == "left" ? [draggedTab, droppedOnTab] : [droppedOnTab, draggedTab],
|
||||
topOrLeft ? [draggedTab, droppedOnTab] : [droppedOnTab, draggedTab],
|
||||
gridType,
|
||||
dropSide == "left" ? 0 : 1
|
||||
topOrLeft ? 0 : 1
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2093,48 +2179,52 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
this._sessionRestoring = true;
|
||||
|
||||
for (const groupData of data) {
|
||||
const group = document.getElementById(groupData.groupId);
|
||||
if (!gBrowser.isTabGroup(group)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Backwards compatibility
|
||||
group.setAttribute("split-view-group", "true");
|
||||
if (!groupData?.layoutTree) {
|
||||
this.splitTabs(group.tabs, group.gridType);
|
||||
delete this._sessionRestoring;
|
||||
return;
|
||||
}
|
||||
|
||||
const deserializeNode = (nodeData) => {
|
||||
if (nodeData.type === "leaf") {
|
||||
const tab = document.getElementById(nodeData.tabId);
|
||||
if (!tab) {
|
||||
return null;
|
||||
}
|
||||
return new nsSplitLeafNode(tab, nodeData.sizeInParent);
|
||||
try {
|
||||
const group = document.getElementById(groupData.groupId);
|
||||
if (!gBrowser.isTabGroup(group)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const splitter = new nsSplitNode(nodeData.direction, nodeData.sizeInParent);
|
||||
splitter._children = [];
|
||||
|
||||
for (const childData of nodeData.children) {
|
||||
const childNode = deserializeNode(childData);
|
||||
if (childNode) {
|
||||
childNode.parent = splitter;
|
||||
splitter._children.push(childNode);
|
||||
}
|
||||
// Backwards compatibility
|
||||
group.setAttribute("split-view-group", "true");
|
||||
if (!groupData?.layoutTree) {
|
||||
this.splitTabs(group.tabs, group.gridType);
|
||||
delete this._sessionRestoring;
|
||||
return;
|
||||
}
|
||||
|
||||
return splitter;
|
||||
};
|
||||
const deserializeNode = (nodeData) => {
|
||||
if (nodeData.type === "leaf") {
|
||||
const tab = document.getElementById(nodeData.tabId);
|
||||
if (!tab) {
|
||||
return null;
|
||||
}
|
||||
return new nsSplitLeafNode(tab, nodeData.sizeInParent);
|
||||
}
|
||||
|
||||
const layout = deserializeNode(groupData.layoutTree);
|
||||
const splitData = this.splitTabs(group.tabs, groupData.gridType, -1);
|
||||
if (splitData) {
|
||||
splitData.layoutTree = layout;
|
||||
} else {
|
||||
gBrowser.removeTabGroup(group);
|
||||
const splitter = new nsSplitNode(nodeData.direction, nodeData.sizeInParent);
|
||||
splitter._children = [];
|
||||
|
||||
for (const childData of nodeData.children) {
|
||||
const childNode = deserializeNode(childData);
|
||||
if (childNode) {
|
||||
childNode.parent = splitter;
|
||||
splitter._children.push(childNode);
|
||||
}
|
||||
}
|
||||
|
||||
return splitter;
|
||||
};
|
||||
|
||||
const layout = deserializeNode(groupData.layoutTree);
|
||||
const splitData = this.splitTabs(group.tabs, groupData.gridType, -1);
|
||||
if (splitData) {
|
||||
splitData.layoutTree = layout;
|
||||
} else {
|
||||
gBrowser.removeTabGroup(group);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Error restoring split view session data:", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2188,14 +2278,16 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
}
|
||||
|
||||
createEmptySplit(rightSide = true) {
|
||||
createEmptySplit(side = "right") {
|
||||
const selectedTab = gBrowser.selectedTab;
|
||||
const emptyTab = gZenWorkspaces._emptyTab;
|
||||
let tabs = rightSide ? [selectedTab, emptyTab] : [emptyTab, selectedTab];
|
||||
const gridType = side === "top" || side === "bottom" ? "hsep" : "vsep";
|
||||
const topOrLeft = side === "top" || side === "left";
|
||||
let tabs = topOrLeft ? [emptyTab, selectedTab] : [selectedTab, emptyTab];
|
||||
const data = {
|
||||
tabs,
|
||||
gridType: "grid",
|
||||
layoutTree: this.calculateLayoutTree(tabs, "grid"),
|
||||
gridType,
|
||||
layoutTree: this.calculateLayoutTree(tabs, gridType),
|
||||
};
|
||||
this.#withoutSplitViewTransition(() => {
|
||||
this._data.push(data);
|
||||
@@ -2230,9 +2322,9 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
gBrowser.selectedTab = selectedTab;
|
||||
this.resetTabState(emptyTab, false);
|
||||
this.splitTabs(
|
||||
rightSide ? [selectedTab, newSelectedTab] : [newSelectedTab, selectedTab],
|
||||
"grid",
|
||||
rightSide ? 1 : 0
|
||||
topOrLeft ? [newSelectedTab, selectedTab] : [selectedTab, newSelectedTab],
|
||||
gridType,
|
||||
topOrLeft ? 0 : 1
|
||||
);
|
||||
} else {
|
||||
cleanup();
|
||||
|
||||
@@ -44,12 +44,12 @@
|
||||
#zen-splitview-dropzone {
|
||||
position: absolute !important;
|
||||
|
||||
margin: var(--zen-split-column-gap) var(--zen-split-row-gap) !important;
|
||||
margin-bottom: 0 !important;
|
||||
margin-left: 0 !important;
|
||||
margin: var(--zen-split-column-gap) var(--zen-split-row-gap);
|
||||
margin-bottom: 0;
|
||||
margin-left: 0;
|
||||
|
||||
&.browserSidebarContainer:not([zen-split='true']) {
|
||||
margin-top: 0 !important;
|
||||
margin-top: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
@@ -204,6 +204,15 @@
|
||||
overflow: hidden;
|
||||
will-change: width, margin-left;
|
||||
|
||||
&[side='top'],
|
||||
&[side='bottom'] {
|
||||
width: 100%;
|
||||
|
||||
&[has-split-view='true'] {
|
||||
width: calc(100% - var(--zen-element-separation));
|
||||
}
|
||||
}
|
||||
|
||||
&[side='right'] {
|
||||
right: 0;
|
||||
|
||||
@@ -211,6 +220,10 @@
|
||||
right: var(--zen-element-separation);
|
||||
}
|
||||
}
|
||||
|
||||
&[side='bottom'] {
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#zen-split-view-drag-image {
|
||||
|
||||
@@ -141,6 +141,7 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
|
||||
tab.removeEventListener("click", tab._zenClickEventListener);
|
||||
delete tab._zenClickEventListener;
|
||||
}
|
||||
this.resetPinChangedUrl(tab);
|
||||
break;
|
||||
default:
|
||||
console.warn("ZenPinnedTabManager: Unhandled tab event", action);
|
||||
@@ -530,8 +531,16 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
|
||||
const isVisible = contextTab.pinned && !contextTab.multiselected;
|
||||
const isEssential = contextTab.getAttribute("zen-essential");
|
||||
const zenAddEssential = document.getElementById("context_zen-add-essential");
|
||||
document.getElementById("context_zen-reset-pinned-tab").hidden = !isVisible;
|
||||
document.getElementById("context_zen-replace-pinned-url-with-current").hidden = !isVisible;
|
||||
const zenResetPinnedTab = document.getElementById("context_zen-reset-pinned-tab");
|
||||
const zenReplacePinnedUrl = document.getElementById(
|
||||
"context_zen-replace-pinned-url-with-current"
|
||||
);
|
||||
[zenResetPinnedTab, zenReplacePinnedUrl].forEach((element) => {
|
||||
if (element) {
|
||||
element.hidden = !isVisible;
|
||||
document.l10n.setArgs(element, { isEssential });
|
||||
}
|
||||
});
|
||||
zenAddEssential.hidden = isEssential || !!contextTab.group;
|
||||
document.l10n
|
||||
.formatValue("tab-context-zen-add-essential-badge", {
|
||||
@@ -558,13 +567,50 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
|
||||
// eslint-disable-next-line complexity
|
||||
moveToAnotherTabContainerIfNecessary(event, movingTabs) {
|
||||
if (!this.enabled) {
|
||||
return false;
|
||||
moveToAnotherTabContainerIfNecessary(event, draggedTab, movingTabs, dropIndex) {
|
||||
let newIndex = dropIndex;
|
||||
let fromDifferentWindow = false;
|
||||
movingTabs = Array.from(movingTabs || draggedTab)
|
||||
.reverse()
|
||||
.map((tab) => {
|
||||
if (!gBrowser.isTab(tab)) {
|
||||
return tab;
|
||||
}
|
||||
let workspaceId;
|
||||
if (tab.ownerGlobal !== window) {
|
||||
fromDifferentWindow = true;
|
||||
if (
|
||||
!tab.hasAttribute("zen-essential") &&
|
||||
tab.getAttribute("zen-workspace-id") != gZenWorkspaces.activeWorkspace
|
||||
) {
|
||||
workspaceId = gZenWorkspaces.activeWorkspace;
|
||||
tab.ownerGlobal.gBrowser.selectedTab = tab.ownerGlobal.gBrowser._findTabToBlurTo(
|
||||
tab,
|
||||
movingTabs
|
||||
);
|
||||
tab.ownerGlobal.gZenWorkspaces.moveTabToWorkspace(tab, workspaceId);
|
||||
}
|
||||
// Move the tabs into this window. To avoid multiple tab-switches in
|
||||
// the original window, the selected tab should be adopted last.
|
||||
tab = gBrowser.adoptTab(tab, {
|
||||
elementIndex: newIndex,
|
||||
selectTab: tab == draggedTab,
|
||||
});
|
||||
if (tab) {
|
||||
++newIndex;
|
||||
}
|
||||
if (workspaceId) {
|
||||
tab.setAttribute("zen-workspace-id", workspaceId);
|
||||
}
|
||||
}
|
||||
return tab;
|
||||
});
|
||||
if (fromDifferentWindow) {
|
||||
gBrowser.addRangeToMultiSelectedTabs(
|
||||
gBrowser.tabContainer.dragAndDropElements[dropIndex],
|
||||
gBrowser.tabContainer.dragAndDropElements[newIndex - 1]
|
||||
);
|
||||
}
|
||||
movingTabs = movingTabs.map((tab) => {
|
||||
return tab.ownerGlobal !== window ? gBrowser.adoptTab(tab) : tab;
|
||||
});
|
||||
try {
|
||||
const pinnedTabsTarget = event.target.closest(
|
||||
":is(.zen-current-workspace-indicator, .zen-workspace-pinned-tabs-section)"
|
||||
@@ -586,9 +632,9 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
|
||||
// Remove group labels from the moving tabs and replace it
|
||||
// with the sub tabs
|
||||
for (let i = 0; i < movingTabs.length; i++) {
|
||||
const draggedTab = movingTabs[i];
|
||||
if (gBrowser.isTabGroupLabel(draggedTab)) {
|
||||
const group = draggedTab.group;
|
||||
const tab = movingTabs[i];
|
||||
if (gBrowser.isTabGroupLabel(tab)) {
|
||||
const group = tab.group;
|
||||
// remove label and add sub tabs to moving tabs
|
||||
if (group) {
|
||||
movingTabs.splice(i, 1, ...group.tabs);
|
||||
@@ -599,32 +645,32 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
|
||||
let isVertical = this.expandedSidebarMode;
|
||||
let moved = false;
|
||||
let hasActuallyMoved;
|
||||
for (const draggedTab of movingTabs) {
|
||||
for (const tab of movingTabs) {
|
||||
let isRegularTabs = false;
|
||||
// Check for essentials container
|
||||
if (essentialTabsTarget) {
|
||||
if (!draggedTab.hasAttribute("zen-essential") && !draggedTab?.group) {
|
||||
if (!tab.hasAttribute("zen-essential") && !tab?.group?.hasAttribute("split-view-group")) {
|
||||
moved = true;
|
||||
isVertical = false;
|
||||
hasActuallyMoved = this.addToEssentials(draggedTab);
|
||||
hasActuallyMoved = this.addToEssentials(tab);
|
||||
}
|
||||
}
|
||||
// Check for pinned tabs container
|
||||
else if (pinnedTabsTarget) {
|
||||
if (!draggedTab.pinned) {
|
||||
gBrowser.pinTab(draggedTab);
|
||||
} else if (draggedTab.hasAttribute("zen-essential")) {
|
||||
this.removeEssentials(draggedTab, false);
|
||||
if (!tab.pinned) {
|
||||
gBrowser.pinTab(tab);
|
||||
} else if (tab.hasAttribute("zen-essential")) {
|
||||
this.removeEssentials(tab, false);
|
||||
moved = true;
|
||||
}
|
||||
}
|
||||
// Check for normal tabs container
|
||||
else if (tabsTarget || event.target.id === "zen-tabs-wrapper") {
|
||||
if (draggedTab.pinned && !draggedTab.hasAttribute("zen-essential")) {
|
||||
gBrowser.unpinTab(draggedTab);
|
||||
if (tab.pinned && !tab.hasAttribute("zen-essential")) {
|
||||
gBrowser.unpinTab(tab);
|
||||
isRegularTabs = true;
|
||||
} else if (draggedTab.hasAttribute("zen-essential")) {
|
||||
this.removeEssentials(draggedTab);
|
||||
} else if (tab.hasAttribute("zen-essential")) {
|
||||
this.removeEssentials(tab);
|
||||
moved = true;
|
||||
isRegularTabs = true;
|
||||
}
|
||||
@@ -665,7 +711,7 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
|
||||
elementIndex++;
|
||||
}
|
||||
|
||||
gBrowser.moveTabTo(draggedTab, {
|
||||
gBrowser.moveTabTo(tab, {
|
||||
elementIndex,
|
||||
forceUngrouped: targetElem?.group?.collapsed !== false,
|
||||
});
|
||||
|
||||
@@ -22,7 +22,7 @@ zen-essentials-promo {
|
||||
outline: 1px dashed currentColor;
|
||||
}
|
||||
|
||||
:root:not([zen-sidebar-expanded="true"]) & {
|
||||
:root:is(:not([zen-sidebar-expanded="true"]), [zen-unsynced-window="true"]) & {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
@@ -209,7 +209,7 @@
|
||||
}
|
||||
|
||||
:root[zen-unsynced-window="true"] & {
|
||||
transform: translateY(-4px);
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,12 @@
|
||||
# This file is autogenerated by scripts/import_external_tests.py
|
||||
# Do not edit manually.
|
||||
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
"safebrowsing/browser.toml",
|
||||
"sandbox/browser.toml",
|
||||
"shell/browser.toml",
|
||||
"tooltiptext/browser.toml",
|
||||
]
|
||||
XPCSHELL_TESTS_MANIFESTS += [
|
||||
]
|
||||
@@ -682,13 +682,6 @@ async function testFileAccessWindowsOnly() {
|
||||
let tests = [];
|
||||
|
||||
let extDir = GetPerUserExtensionDir();
|
||||
// We used to unconditionally create this directory from Firefox, but that
|
||||
// was dropped in bug 2001887. The value of this directory is questionable;
|
||||
// the test was added in Firefox 56 (bug 1403744) to cover legacy add-ons,
|
||||
// but legacy add-on support was discontinued in Firefox 57, and we stopped
|
||||
// sideloading add-ons from this directory on all builds except ESR in
|
||||
// Firefox 74 (bug 1602840).
|
||||
await IOUtils.makeDirectory(extDir.path);
|
||||
tests.push({
|
||||
desc: "per-user extensions dir",
|
||||
ok: true,
|
||||
|
||||
@@ -22,13 +22,6 @@ add_setup(async function setup() {
|
||||
const xdgConfigHome = Services.env.get("XDG_CONFIG_HOME");
|
||||
Assert.greater(xdgConfigHome.length, 1, "XDG_CONFIG_HOME is defined");
|
||||
|
||||
// Verify the profile directory is inside XDG_CONFIG_HOME
|
||||
const profileDir = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||
Assert.ok(
|
||||
profileDir.path.startsWith(xdgConfigHome),
|
||||
`Profile directory (${profileDir.path}) should be inside XDG_CONFIG_HOME (${xdgConfigHome})`
|
||||
);
|
||||
|
||||
// If it is there, do actual testing
|
||||
sanityChecks();
|
||||
});
|
||||
|
||||
@@ -12,14 +12,11 @@ support-files = [
|
||||
"browser_content_sandbox_utils.js",
|
||||
"browser_content_sandbox_fs_tests.js",
|
||||
]
|
||||
test-directories = [
|
||||
"/tmp/.xdg_default_test",
|
||||
"/tmp/.xdg_default_test/.config/mozilla/firefox/xdg_default_profile",
|
||||
]
|
||||
# .config needs to exists for the sandbox to properly add it
|
||||
test-directories = ["/tmp/.xdg_default_test", "/tmp/.xdg_default_test/.config"]
|
||||
environment = [
|
||||
"HOME=/tmp/.xdg_default_test",
|
||||
]
|
||||
profile-path = "/tmp/.xdg_default_test/.config/mozilla/firefox/xdg_default_profile"
|
||||
|
||||
["browser_content_sandbox_fs_xdg_default.js"]
|
||||
run-if = ["os == 'linux'"]
|
||||
|
||||
@@ -12,17 +12,12 @@ support-files = [
|
||||
"browser_content_sandbox_utils.js",
|
||||
"browser_content_sandbox_fs_tests.js",
|
||||
]
|
||||
test-directories = [
|
||||
"/tmp/.xdg_mozLegacyHome_test/.config",
|
||||
"/tmp/.xdg_config_home_test",
|
||||
"/tmp/.xdg_mozLegacyHome_test/.mozilla/firefox/xdg_mozLegacyHome_profile",
|
||||
]
|
||||
test-directories = ["/tmp/.xdg_mozLegacyHome_test/.config", "/tmp/.xdg_config_home_test"]
|
||||
environment = [
|
||||
"XDG_CONFIG_HOME=/tmp/.xdg_config_home_test",
|
||||
"HOME=/tmp/.xdg_mozLegacyHome_test",
|
||||
"MOZ_LEGACY_HOME=1",
|
||||
]
|
||||
profile-path = "/tmp/.xdg_mozLegacyHome_test/.mozilla/firefox/xdg_mozLegacyHome_profile"
|
||||
|
||||
["browser_content_sandbox_fs_xdg_mozLegacyHome.js"]
|
||||
run-if = ["os == 'linux'"]
|
||||
|
||||
@@ -11,15 +11,11 @@ support-files = [
|
||||
"browser_content_sandbox_utils.js",
|
||||
"browser_content_sandbox_fs_tests.js",
|
||||
]
|
||||
test-directories = [
|
||||
"/tmp/.xdg_config_home_test",
|
||||
"/tmp/.xdg_config_home_test/mozilla/firefox/xdg_config_home_profile",
|
||||
]
|
||||
test-directories = "/tmp/.xdg_config_home_test"
|
||||
environment = [
|
||||
"XDG_CONFIG_HOME=/tmp/.xdg_config_home_test",
|
||||
"MOZ_LEGACY_HOME=0",
|
||||
]
|
||||
profile-path = "/tmp/.xdg_config_home_test/mozilla/firefox/xdg_config_home_profile"
|
||||
|
||||
["browser_content_sandbox_fs_xdg_xdgConfigHome.js"]
|
||||
run-if = [
|
||||
|
||||
@@ -57,12 +57,6 @@ window.ZenWorkspaceBookmarksStorage = {
|
||||
CREATE INDEX IF NOT EXISTS idx_bookmarks_workspaces_changes
|
||||
ON zen_bookmarks_workspaces_changes(bookmark_guid, workspace_uuid)
|
||||
`);
|
||||
|
||||
// Before, workspace_uuid was a FOREIGN KEY, not anymore, so we need to drop the constraint
|
||||
// This is a no-op if the constraint doesn't exist
|
||||
await db.execute(`
|
||||
PRAGMA foreign_keys = OFF;
|
||||
`);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
@@ -231,7 +231,7 @@ class nsZenWorkspaces {
|
||||
}
|
||||
}
|
||||
|
||||
async selectEmptyTab(newTabTarget = null, selectURLBar = true) {
|
||||
async selectEmptyTab(newTabTarget = null) {
|
||||
// Validate browser state first
|
||||
if (!this._validateBrowserState()) {
|
||||
console.warn("Browser state invalid for empty tab selection");
|
||||
@@ -251,30 +251,6 @@ class nsZenWorkspaces {
|
||||
!this._emptyTab.ownerGlobal.closed &&
|
||||
gZenVerticalTabsManager._canReplaceNewTab
|
||||
) {
|
||||
// Only set up URL bar selection if we're switching to a different tab
|
||||
if (gBrowser.selectedTab !== this._emptyTab && selectURLBar) {
|
||||
const tabSelectListener = () => {
|
||||
// Remove the event listener first to prevent any chance of multiple executions
|
||||
window.removeEventListener("TabSelect", tabSelectListener);
|
||||
|
||||
// Use requestAnimationFrame to ensure DOM is updated
|
||||
requestAnimationFrame(() => {
|
||||
// Then use setTimeout to ensure browser has time to process tab switch
|
||||
setTimeout(() => {
|
||||
if (gURLBar) {
|
||||
try {
|
||||
gURLBar.select();
|
||||
} catch (e) {
|
||||
console.warn("Error selecting URL bar:", e);
|
||||
}
|
||||
}
|
||||
}, 50);
|
||||
});
|
||||
};
|
||||
|
||||
window.addEventListener("TabSelect", tabSelectListener, { once: true });
|
||||
}
|
||||
|
||||
// Safely switch to the empty tab using our debounced method
|
||||
const success = await this._safelySelectTab(this._emptyTab);
|
||||
if (!success) {
|
||||
@@ -807,7 +783,7 @@ class nsZenWorkspaces {
|
||||
chromeFlags & Ci.nsIWebBrowserChrome.CHROME_MENUBAR;
|
||||
return this._shouldHaveWorkspaces;
|
||||
}
|
||||
return this._shouldHaveWorkspaces;
|
||||
return this._shouldHaveWorkspaces && !document.documentElement.hasAttribute("taskbartab");
|
||||
}
|
||||
|
||||
get isPrivateWindow() {
|
||||
@@ -1044,11 +1020,19 @@ class nsZenWorkspaces {
|
||||
delete this._initialTab;
|
||||
}
|
||||
|
||||
if (gZenVerticalTabsManager._canReplaceNewTab && showed) {
|
||||
BrowserCommands.openTab();
|
||||
} else if (!showed) {
|
||||
gBrowser.selectedBrowser.focus();
|
||||
}
|
||||
showed &&= Services.prefs.getBoolPref("zen.urlbar.open-on-startup", true);
|
||||
|
||||
// Wait for the next event loop to ensure that the startup focus logic by
|
||||
// firefox has finished doing it's thing.
|
||||
setTimeout(() => {
|
||||
setTimeout(() => {
|
||||
if (gZenVerticalTabsManager._canReplaceNewTab && showed) {
|
||||
BrowserCommands.openTab();
|
||||
} else if (!showed) {
|
||||
gBrowser.selectedBrowser.focus();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (
|
||||
!gZenVerticalTabsManager._canReplaceNewTab &&
|
||||
@@ -1124,7 +1108,7 @@ class nsZenWorkspaces {
|
||||
return (
|
||||
!window.toolbar.visible ||
|
||||
Services.prefs.getBoolPref("browser.tabs.closeWindowWithLastTab") ||
|
||||
this.privateWindowOrDisabled
|
||||
(this.privateWindowOrDisabled && !this.isPrivateWindow)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2430,7 +2414,10 @@ class nsZenWorkspaces {
|
||||
if (!this.currentWindowIsSyncing) {
|
||||
containerTabId = parseInt(gBrowser.selectedTab.getAttribute("usercontextid")) || 0;
|
||||
let label = ContextualIdentityService.getUserContextLabel(containerTabId) || "Default";
|
||||
name = this.isPrivateWindow ? "Private " + name : label;
|
||||
name = this.isPrivateWindow ? "Incognito" : label;
|
||||
if (this.isPrivateWindow) {
|
||||
icon = gZenEmojiPicker.getSVGURL("eye.svg");
|
||||
}
|
||||
}
|
||||
let workspace = {
|
||||
uuid: gZenUIManager.generateUuidv4(),
|
||||
|
||||
@@ -156,7 +156,7 @@
|
||||
/* Mark workspaces indicator */
|
||||
.zen-current-workspace-indicator {
|
||||
--indicator-gap: calc(var(--toolbarbutton-inner-padding) - 1px);
|
||||
padding: calc(2px + var(--tab-inline-padding) + var(--zen-toolbox-padding));
|
||||
padding: calc(3px + var(--tab-inline-padding) + var(--zen-toolbox-padding));
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
max-height: var(--zen-workspace-indicator-height);
|
||||
@@ -177,10 +177,10 @@
|
||||
pointer-events: none;
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: var(--zen-toolbox-padding);
|
||||
top: 4px;
|
||||
left: calc(var(--zen-toolbox-padding) + 2px);
|
||||
width: calc(100% - var(--zen-toolbox-padding) * 3);
|
||||
height: calc(100% - var(--zen-toolbox-padding) * 2);
|
||||
width: calc(100% - var(--zen-toolbox-padding) * 2.5);
|
||||
height: calc(100% - 8px);
|
||||
}
|
||||
|
||||
:root[zen-private-window] & {
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
"binaryName": "zen",
|
||||
"version": {
|
||||
"product": "firefox",
|
||||
"version": "147.0.2",
|
||||
"candidate": "147.0.2",
|
||||
"version": "147.0.3",
|
||||
"candidate": "147.0.3",
|
||||
"candidateBuild": 1
|
||||
},
|
||||
"buildOptions": {
|
||||
@@ -20,7 +20,7 @@
|
||||
"brandShortName": "Zen",
|
||||
"brandFullName": "Zen Browser",
|
||||
"release": {
|
||||
"displayVersion": "1.18.2b",
|
||||
"displayVersion": "1.18.5b",
|
||||
"github": {
|
||||
"repo": "zen-browser/desktop"
|
||||
},
|
||||
@@ -54,4 +54,4 @@
|
||||
"licenseType": "MPL-2.0"
|
||||
},
|
||||
"updateHostname": "updates.zen-browser.app"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user