Compare commits

..

25 Commits

Author SHA1 Message Date
mr. m
0e8b8da845 chore: Convert the codebase into modules, p=#11364
* chore: Convert the codebase into modules, b=no-bug, c=common, compact-mode, folders, fonts, glance, images, kbs, media, mods, split-view, tabs, tests, vendor, welcome, workspaces

* feat: Added update popup, b=no-bug, c=media, common
2025-11-20 18:14:46 +01:00
mr. m
3eb3875de9 Merge branch 'dev' of https://github.com/zen-browser/desktop into dev 2025-11-19 19:14:50 +01:00
mr. m
4c5a3aeabb feat: Always show the separator if there are visible tabs, b=closes #11349, c=tabs, workspaces 2025-11-19 19:14:45 +01:00
Mr. M
34e1adddf9 Merge branch 'dev' of https://github.com/zen-browser/desktop into dev 2025-11-19 14:47:44 +01:00
Mr. M
58f97c65e1 feat: Add preference for sidebar dragging, b=no-bug, c=common, workspaces 2025-11-19 14:47:41 +01:00
ramiro
4089dfa18b fix: Split view gap when in compact view and sidebar is on right, b=closes https://github.com/zen-browser/desktop/issues/11269, p=#11357 2025-11-19 12:30:15 +01:00
mr. m
b903a25092 chore: Revert "9f15a61727", p=#11353
This reverts commit 9f15a61727.
2025-11-19 01:59:46 +01:00
mr. m
306b8a6171 Merge branch 'dev' of https://github.com/zen-browser/desktop into dev 2025-11-18 21:03:04 +01:00
mr. m
9f15a61727 chore: Apply patches from https://bugzilla.mozilla.org/show_bug.cgi?id=1993474, p=#11351 c=no-component 2025-11-18 21:02:58 +01:00
mr. m
4aef6bb285 chore: Bump version, b=no-bug, c=no-component 2025-11-18 21:02:28 +01:00
Mr. M
72dbe631ec chore: Fixed linter errors, b=no-bug, c=common 2025-11-18 20:45:17 +01:00
Mr. M
a8e5894c95 Merge branch 'dev' of https://github.com/zen-browser/desktop into dev 2025-11-18 20:41:30 +01:00
Mr. M
e5509f607d fix: Fixed position for control center panel on double toolbar, b=no-bug, c=common 2025-11-18 20:40:55 +01:00
ramiro
dfbf4db57f fix: improve drag-and-drop behavior for tab folders, b=closes #11326, p=#11345
Co-authored-by: mr. m <91018726+mr-cheffy@users.noreply.github.com>
2025-11-18 20:24:19 +01:00
mr. m
f948575446 chore: New Crowdin updates, p=#11325 2025-11-18 20:23:48 +01:00
Mr. M
3dbf8446c2 Merge branch 'dev' of https://github.com/zen-browser/desktop into dev 2025-11-18 20:19:28 +01:00
Mr. M
4361efb956 feat: Start using Firefox's split views to prevent memory leaks, b=no-bug, c=common, split-view 2025-11-18 20:16:51 +01:00
mr. m
6ba714e4e4 chore: Sync upstream to Firefox 145.0.1, p=#11347 2025-11-18 17:53:08 +01:00
mr. m
45b20dffda chore: Sync upstream to Firefox 145.0.1-RC, p=#11338 2025-11-18 10:07:36 +01:00
Jun Jie
08996215b2 fix: persist expanded glance tab after closing browser, p=#11336
* fix: persist expanded glance tab after closing browser

* fix lint error
2025-11-18 09:03:53 +01:00
mr. m
dfe932a4c5 Merge branch 'dev' of https://github.com/zen-browser/desktop into dev 2025-11-18 00:31:15 +01:00
mr. m
a61b077d3f fix: Don't resize the sidebar when entering DOM fullscreen, b=no-bug, c=workspaces 2025-11-18 00:31:11 +01:00
Mr. M
f36b84de3c chore: Clean up unused block in macos share method, b=no-bug, c=common 2025-11-17 13:53:45 +01:00
Mr. M
01f10cfc09 feat: Make close and reset icons only appear when hovering the tab, b=no-bug, c=folders, tabs 2025-11-17 13:50:03 +01:00
Mr. M
9a9c1c312c fix: Fixed glance not listening for context menu activations, b=closes #11148, c=common, glance 2025-11-17 11:38:45 +01:00
113 changed files with 10960 additions and 10759 deletions

View File

@@ -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 `145.0`! 🚀
- [`Twilight`](https://zen-browser.app/download?twilight) - Is currently built using Firefox version `RC 145.0`!
- [`Release`](https://zen-browser.app/download) - Is currently built using Firefox version `145.0.1`! 🚀
- [`Twilight`](https://zen-browser.app/download?twilight) - Is currently built using Firefox version `RC 145.0.1`!
### Contributing

View File

@@ -1 +1 @@
1e325bc45d9111518958446ac966fd4e4136d6d5
99a389c2413be0374ee04b10021ed269c0387b45

View File

@@ -121,3 +121,14 @@ zen-site-data-panel-feature-callout-subtitle = Click the icon to manage site set
zen-open-link-in-glance =
.label = Open Link in Glance
.accesskey = G
zen-sidebar-notification-updated-heading = Update Complete!
# See ZenSidebarNotification.mjs to see how these would be used
zen-sidebar-notification-updated-label = What's new in { -brand-short-name }
zen-sidebar-notification-updated-tooltip =
.title = View Release Notes
zen-sidebar-notification-restart-safe-mode-label = Something broke?
zen-sidebar-notification-restart-safe-mode-tooltip =
.title = Restart in Safe Mode

View File

@@ -45,9 +45,9 @@ pane-settings-workspaces-title = Ruang Kerja
zen-tabs-unloader-enabled =
.label = Aktifkan Pelepas Tab
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
.label = Tutup tab dan beralih ke tab pemiliknya (atau tab yang terakhir digunakan) saat kembali tanpa riwayat
zen-tabs-cycle-by-attribute =
.label = Ctrl+Tab cycles within Essential or Workspace tabs only
.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
@@ -311,4 +311,4 @@ zen-devtools-toggle-performance-shortcut = Ubah Performance
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 = Close All Unpinned Tabs
zen-close-all-unpinned-tabs-shortcut = Tutup Semua Tab yang Tidak Disematkan

View File

@@ -8,9 +8,9 @@ tab-context-zen-reset-pinned-tab =
.label = Kembalikan ke URL Awal
.accesskey = R
tab-context-zen-add-essential =
.label = Add to Essentials
.label = Tambahkan ke Essentials
.accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-add-essential-badge = { $num } / { $max } slot terisi
tab-context-zen-remove-essential =
.label = Hapus dari Essentials
.accesskey = R
@@ -96,5 +96,5 @@ zen-site-data-setting-site-protection = Perlindungan Pelacakan
zen-site-data-panel-feature-callout-title = Rumah baru untuk add-on, izin, dan lainnya
zen-site-data-panel-feature-callout-subtitle = Klik ikon untuk mengelola pengaturan situs, melihat info keamanan, mengakses ekstensi, dan melakukan tindakan umum.
zen-open-link-in-glance =
.label = Open Link in Glance
.label = Buka Tautan di Glance
.accesskey = G

View File

@@ -59,7 +59,7 @@ zen-workspaces-delete-workspace-title = Delete Workspace?
zen-workspaces-delete-workspace-body = Apakah Anda yakin ingin menghapus { $name }? Tindakan ini tidak bisa dibatalkan.
# Note that the html tag MUST not be changed or removed, as it is used to better
# display the shortcut in the toast notification.
zen-workspaces-close-all-unpinned-tabs-toast = Tabs Closed! Use <span>{ $shortcut }</span> to undo.
zen-workspaces-close-all-unpinned-tabs-toast = Tab Ditutup! Gunakan <span>{ $shortcut }</span> untuk membatalkan.
zen-workspaces-close-all-unpinned-tabs-title =
.label = Clear
.tooltiptext = Close all unpinned tabs
.label = Bersihkan
.tooltiptext = Tutup semua tab yang tidak disematkan

158
package-lock.json generated
View File

@@ -9,7 +9,7 @@
"version": "1.0.0",
"license": "MPL-2.0",
"dependencies": {
"@zen-browser/surfer": "^1.11.22"
"@zen-browser/surfer": "^1.11.23"
},
"devDependencies": {
"@babel/preset-typescript": "^7.27.0",
@@ -35,7 +35,6 @@
"integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.24"
@@ -65,7 +64,6 @@
"integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=6.9.0"
}
@@ -108,7 +106,6 @@
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"license": "ISC",
"peer": true,
"bin": {
"semver": "bin/semver.js"
}
@@ -149,7 +146,6 @@
"integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/compat-data": "^7.26.8",
"@babel/helper-validator-option": "^7.25.9",
@@ -167,7 +163,6 @@
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"license": "ISC",
"peer": true,
"bin": {
"semver": "bin/semver.js"
}
@@ -341,7 +336,6 @@
"integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/template": "^7.27.0",
"@babel/types": "^7.27.0"
@@ -617,13 +611,6 @@
"url": "https://opencollective.com/eslint"
}
},
"node_modules/@eslint/eslintrc/node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true,
"license": "Python-2.0"
},
"node_modules/@eslint/eslintrc/node_modules/globals": {
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
@@ -637,19 +624,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@eslint/eslintrc/node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dev": true,
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/@eslint/eslintrc/node_modules/strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
@@ -838,51 +812,51 @@
}
},
"node_modules/@oozcitak/dom": {
"version": "1.15.10",
"resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-1.15.10.tgz",
"integrity": "sha512-0JT29/LaxVgRcGKvHmSrUTEvZ8BXvZhGl2LASRUgHqDTC1M5g1pLmVv56IYNyt3bG2CUjDkc67wnyZC14pbQrQ==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-2.0.1.tgz",
"integrity": "sha512-Un5k8MKqGak1LQM/behcHylmGdRopBXZax19weVedEAIrOCRZooY+MvX4Ehcz0ftOEPgYZ7vjIm/+MokVBFO3w==",
"license": "MIT",
"dependencies": {
"@oozcitak/infra": "1.0.8",
"@oozcitak/url": "1.0.4",
"@oozcitak/util": "8.3.8"
"@oozcitak/infra": "^2.0.1",
"@oozcitak/url": "^2.0.1",
"@oozcitak/util": "^9.0.2"
},
"engines": {
"node": ">=8.0"
"node": ">=20.0"
}
},
"node_modules/@oozcitak/infra": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.8.tgz",
"integrity": "sha512-JRAUc9VR6IGHOL7OGF+yrvs0LO8SlqGnPAMqyzOuFZPSZSXI7Xf2O9+awQPSMXgIWGtgUf/dA6Hs6X6ySEaWTg==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-2.0.1.tgz",
"integrity": "sha512-TtjI+kducm0ExL3OTKglPLkAIQ3alq0Otbokml62haZESfQaL3ojLJxl7+UTBhWCkBBuCshzGEEYmX5MXo8WOg==",
"license": "MIT",
"dependencies": {
"@oozcitak/util": "8.3.8"
"@oozcitak/util": "~9.0.2"
},
"engines": {
"node": ">=6.0"
"node": ">=20.0"
}
},
"node_modules/@oozcitak/url": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@oozcitak/url/-/url-1.0.4.tgz",
"integrity": "sha512-kDcD8y+y3FCSOvnBI6HJgl00viO/nGbQoCINmQ0h98OhnGITrWR3bOGfwYCthgcrV8AnTJz8MzslTQbC3SOAmw==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@oozcitak/url/-/url-2.0.1.tgz",
"integrity": "sha512-lLHUQUyYy86q+qbALr0TMVh+VQAYwNGbsxBx4LhfjvkNYG0hgAwWtq7ePebGs2nEhZmmIFl24ikuCpH2r5d3+A==",
"license": "MIT",
"dependencies": {
"@oozcitak/infra": "1.0.8",
"@oozcitak/util": "8.3.8"
"@oozcitak/infra": "^2.0.1",
"@oozcitak/util": "^9.0.2"
},
"engines": {
"node": ">=8.0"
"node": ">=20.0"
}
},
"node_modules/@oozcitak/util": {
"version": "8.3.8",
"resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-8.3.8.tgz",
"integrity": "sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ==",
"version": "9.0.4",
"resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-9.0.4.tgz",
"integrity": "sha512-kmx1hRJlsvxiTCpK97off59LqSEOtkWOPe4rdfFL8TjZtihYSTVNObIfc86jtLngfnuIuuTRt+TUCgRS220RSQ==",
"license": "MIT",
"engines": {
"node": ">=8.0"
"node": ">=20.0"
}
},
"node_modules/@resvg/resvg-js": {
@@ -1135,9 +1109,9 @@
"license": "MIT"
},
"node_modules/@zen-browser/surfer": {
"version": "1.11.22",
"resolved": "https://registry.npmjs.org/@zen-browser/surfer/-/surfer-1.11.22.tgz",
"integrity": "sha512-fvV+8stPXJDyX/6lv4bvgkxq1hNGyJJyOU1ysjJSrElxo9CerB35XU8LMjAs6SjuV1olLMILg2DwCIP2gVn0+Q==",
"version": "1.11.23",
"resolved": "https://registry.npmjs.org/@zen-browser/surfer/-/surfer-1.11.23.tgz",
"integrity": "sha512-nPJ8oH1r4yncPCymuVxFRJMKbj9elpLIuSMW7botJT1UpyTKeGPrpFukpc+fq4U8TXa1tNddpoUvI8ZRfk0sxA==",
"license": "MPL-2.0",
"dependencies": {
"@resvg/resvg-js": "^1.4.0",
@@ -1161,7 +1135,7 @@
"semver": "^7.3.7",
"sharp": "^0.32.6",
"tiny-glob": "^0.2.9",
"xmlbuilder2": "^3.0.2"
"xmlbuilder2": "^4.0.0"
},
"bin": {
"surfer": "dist/index.js"
@@ -1173,6 +1147,7 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -1252,13 +1227,10 @@
}
},
"node_modules/argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"license": "MIT",
"dependencies": {
"sprintf-js": "~1.0.2"
}
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"license": "Python-2.0"
},
"node_modules/array-buffer-byte-length": {
"version": "1.0.2",
@@ -1846,8 +1818,7 @@
"url": "https://github.com/sponsors/ai"
}
],
"license": "CC-BY-4.0",
"peer": true
"license": "CC-BY-4.0"
},
"node_modules/chalk": {
"version": "4.1.2",
@@ -2034,8 +2005,7 @@
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/core-js-pure": {
"version": "3.41.0",
@@ -2355,8 +2325,7 @@
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.139.tgz",
"integrity": "sha512-GGnRYOTdN5LYpwbIr0rwP/ZHOQSvAF6TG0LSzp28uCBb9JiXHJGmaaKw29qjNJc5bGnnp6kXJqRnGMQoELwi5w==",
"dev": true,
"license": "ISC",
"peer": true
"license": "ISC"
},
"node_modules/emoji-regex": {
"version": "8.0.0",
@@ -2592,7 +2561,6 @@
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=6"
}
@@ -2616,6 +2584,7 @@
"integrity": "sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -3056,19 +3025,6 @@
"url": "https://opencollective.com/eslint"
}
},
"node_modules/esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"license": "BSD-2-Clause",
"bin": {
"esparse": "bin/esparse.js",
"esvalidate": "bin/esvalidate.js"
},
"engines": {
"node": ">=4"
}
},
"node_modules/esquery": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
@@ -3463,7 +3419,6 @@
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=6.9.0"
}
@@ -4409,13 +4364,12 @@
"license": "MIT"
},
"node_modules/js-yaml": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"license": "MIT",
"dependencies": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
@@ -4461,7 +4415,6 @@
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"json5": "lib/cli.js"
},
@@ -4896,7 +4849,6 @@
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
"dev": true,
"license": "ISC",
"peer": true,
"dependencies": {
"yallist": "^3.0.2"
}
@@ -5111,8 +5063,7 @@
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
"integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/normalize-path": {
"version": "3.0.0",
@@ -5568,6 +5519,7 @@
"integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"prettier": "bin/prettier.cjs"
},
@@ -6342,12 +6294,6 @@
"integrity": "sha512-lgxErLl/7A5+vgIIXsh9MbeukOaCb2axgQ+bKCdIE+ibNT4XNYGNCR1qFEGq6F+YDASXK3Fh/c5FgtZchFolxw==",
"license": "MIT"
},
"node_modules/sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
"license": "BSD-3-Clause"
},
"node_modules/stack-base-iterator": {
"version": "1.1.20",
"resolved": "https://registry.npmjs.org/stack-base-iterator/-/stack-base-iterator-1.1.20.tgz",
@@ -6982,7 +6928,6 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"escalade": "^3.2.0",
"picocolors": "^1.1.1"
@@ -7236,18 +7181,18 @@
"license": "ISC"
},
"node_modules/xmlbuilder2": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-3.1.1.tgz",
"integrity": "sha512-WCSfbfZnQDdLQLiMdGUQpMxxckeQ4oZNMNhLVkcekTu7xhD4tuUDyAPoY8CwXvBYE6LwBHd6QW2WZXlOWr1vCw==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-4.0.0.tgz",
"integrity": "sha512-zIoY033NGmbzHX1cYOGKNfeWpZyiGLzXGHNoxQ6tR/R+WqT7mqz+EDtFdPwqnhIms6vHz9BNtMS47DiGPyGfwg==",
"license": "MIT",
"dependencies": {
"@oozcitak/dom": "1.15.10",
"@oozcitak/infra": "1.0.8",
"@oozcitak/util": "8.3.8",
"js-yaml": "3.14.1"
"@oozcitak/dom": "^2.0.1",
"@oozcitak/infra": "^2.0.1",
"@oozcitak/util": "^9.0.4",
"js-yaml": "^4.1.0"
},
"engines": {
"node": ">=12.0"
"node": ">=20.0"
}
},
"node_modules/xtend": {
@@ -7264,8 +7209,7 @@
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
"dev": true,
"license": "ISC",
"peer": true
"license": "ISC"
},
"node_modules/yaml": {
"version": "2.7.0",

View File

@@ -49,7 +49,7 @@
},
"homepage": "https://github.com/zen-browser/desktop#readme",
"dependencies": {
"@zen-browser/surfer": "^1.11.22"
"@zen-browser/surfer": "^1.11.23"
},
"devDependencies": {
"@babel/preset-typescript": "^7.27.0",

6
prefs/zen/updates.yaml Normal file
View File

@@ -0,0 +1,6 @@
# 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/.
- name: zen.updates.show-update-notification
value: true

View File

@@ -43,11 +43,8 @@
- name: zen.view.drag-and-drop.move-over-threshold
value: 70
- name: zen.view.drag-and-drop.drop-inside-upper-threshold
value: 80
- name: zen.view.drag-and-drop.drop-inside-lower-threshold
value: 30
- name: zen.view.drag-and-drop.edge-zone-threshold
value: 25
- name: zen.view.context-menu.refresh
value: false
@@ -60,3 +57,6 @@
- name: zen.view.show-clear-tabs-button
value: true
- name: zen.view.draggable-sidebar
value: true

View File

@@ -43,18 +43,19 @@
<script type="text/javascript" src="chrome://browser/content/ZenPreloadedScripts.js"></script>
# Scripts used all over the browser
<script type="text/javascript" src="chrome://browser/content/ZenUIManager.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenFolder.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenFolders.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenMods.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenCompactMode.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenPinnedTabsStorage.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenWorkspacesStorage.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenPinnedTabManager.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenGradientGenerator.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenViewSplitter.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenGlanceManager.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenMediaController.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenDownloadAnimation.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenEmojiPicker.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenWorkspaceCreation.mjs"></script>
<script type="module" src="chrome://browser/content/ZenUIManager.mjs"></script>
<script type="module" src="chrome://browser/content/zen-components/ZenFolder.mjs"></script>
<script type="module" src="chrome://browser/content/zen-components/ZenCompactMode.mjs"></script>
<script type="module" src="chrome://browser/content/zen-components/ZenPinnedTabsStorage.mjs"></script>
<script type="module" src="chrome://browser/content/zen-components/ZenWorkspacesStorage.mjs"></script>
<script type="module" src="chrome://browser/content/zen-components/ZenMediaController.mjs"></script>
<script type="module" src="chrome://browser/content/zen-components/ZenWorkspaceCreation.mjs"></script>
<script type="module" src="chrome://browser/content/zen-components/ZenGlanceManager.mjs"></script>
<script type="module" src="chrome://browser/content/zen-components/ZenPinnedTabManager.mjs"></script>
<script type="module" src="chrome://browser/content/zen-components/ZenViewSplitter.mjs"></script>
<script type="module" src="chrome://browser/content/zen-components/ZenFolders.mjs"></script>
<script type="module" src="chrome://browser/content/zen-components/ZenDownloadAnimation.mjs"></script>
<script type="module" src="chrome://browser/content/zen-components/ZenEmojiPicker.mjs"></script>
<script type="module" src="chrome://browser/content/zen-components/ZenMods.mjs"></script>

View File

@@ -2,104 +2,18 @@
# 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/.
content/browser/zenThemeModifier.js (../../zen/common/zenThemeModifier.js)
content/browser/ZenStartup.mjs (../../zen/common/ZenStartup.mjs)
content/browser/ZenPreloadedScripts.js (../../zen/common/ZenPreloadedScripts.js)
content/browser/zen-sets.js (../../zen/common/zen-sets.js)
content/browser/ZenUIManager.mjs (../../zen/common/ZenUIManager.mjs)
content/browser/zen-components/ZenCommonUtils.mjs (../../zen/common/ZenCommonUtils.mjs)
content/browser/zen-components/ZenSessionStore.mjs (../../zen/common/ZenSessionStore.mjs)
content/browser/zen-components/ZenEmojisData.min.mjs (../../zen/common/emojis/ZenEmojisData.min.mjs)
content/browser/zen-components/ZenEmojiPicker.mjs (../../zen/common/emojis/ZenEmojiPicker.mjs)
content/browser/zen-components/ZenHasPolyfill.mjs (../../zen/common/ZenHasPolyfill.mjs)
* content/browser/zen-styles/zen-theme.css (../../zen/common/styles/zen-theme.css)
content/browser/zen-styles/zen-buttons.css (../../zen/common/styles/zen-buttons.css)
content/browser/zen-styles/zen-browser-ui.css (../../zen/common/styles/zen-browser-ui.css)
content/browser/zen-styles/zen-animations.css (../../zen/common/styles/zen-animations.css)
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-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)
content/browser/zen-styles/zen-branding.css (../../zen/common/styles/zen-branding.css)
content/browser/zen-styles/zen-panels/bookmarks.css (../../zen/common/styles/zen-panels/bookmarks.css)
content/browser/zen-styles/zen-panels/print.css (../../zen/common/styles/zen-panels/print.css)
content/browser/zen-styles/zen-panels/dialog.css (../../zen/common/styles/zen-panels/dialog.css)
content/browser/zen-components/ZenCompactMode.mjs (../../zen/compact-mode/ZenCompactMode.mjs)
* content/browser/zen-styles/zen-compact-mode.css (../../zen/compact-mode/zen-compact-mode.css)
content/browser/zen-components/ZenViewSplitter.mjs (../../zen/split-view/ZenViewSplitter.mjs)
* content/browser/zen-styles/zen-decks.css (../../zen/split-view/zen-decks.css)
content/browser/zen-components/ZenMods.mjs (../../zen/mods/ZenMods.mjs)
content/browser/zen-components/ZenWorkspaceIcons.mjs (../../zen/workspaces/ZenWorkspaceIcons.mjs)
content/browser/zen-components/ZenWorkspace.mjs (../../zen/workspaces/ZenWorkspace.mjs)
content/browser/zen-components/ZenWorkspaces.mjs (../../zen/workspaces/ZenWorkspaces.mjs)
content/browser/zen-components/ZenWorkspaceCreation.mjs (../../zen/workspaces/ZenWorkspaceCreation.mjs)
content/browser/zen-components/ZenWorkspacesStorage.mjs (../../zen/workspaces/ZenWorkspacesStorage.mjs)
content/browser/zen-components/ZenWorkspacesSync.mjs (../../zen/workspaces/ZenWorkspacesSync.mjs)
content/browser/zen-components/ZenGradientGenerator.mjs (../../zen/workspaces/ZenGradientGenerator.mjs)
* content/browser/zen-styles/zen-workspaces.css (../../zen/workspaces/zen-workspaces.css)
content/browser/zen-styles/zen-gradient-generator.css (../../zen/workspaces/zen-gradient-generator.css)
content/browser/zen-components/ZenKeyboardShortcuts.mjs (../../zen/kbs/ZenKeyboardShortcuts.mjs)
content/browser/zen-components/ZenPinnedTabsStorage.mjs (../../zen/tabs/ZenPinnedTabsStorage.mjs)
content/browser/zen-components/ZenPinnedTabManager.mjs (../../zen/tabs/ZenPinnedTabManager.mjs)
* content/browser/zen-styles/zen-tabs.css (../../zen/tabs/zen-tabs.css)
content/browser/zen-styles/zen-tabs/vertical-tabs.css (../../zen/tabs/zen-tabs/vertical-tabs.css)
content/browser/zen-components/ZenGlanceManager.mjs (../../zen/glance/ZenGlanceManager.mjs)
content/browser/zen-styles/zen-glance.css (../../zen/glance/zen-glance.css)
content/browser/zen-components/ZenFolder.mjs (../../zen/folders/ZenFolder.mjs)
content/browser/zen-components/ZenFolders.mjs (../../zen/folders/ZenFolders.mjs)
content/browser/zen-styles/zen-folders.css (../../zen/folders/zen-folders.css)
content/browser/zen-components/ZenWelcome.mjs (../../zen/welcome/ZenWelcome.mjs)
content/browser/zen-styles/zen-welcome.css (../../zen/welcome/zen-welcome.css)
content/browser/zen-components/ZenMediaController.mjs (../../zen/media/ZenMediaController.mjs)
content/browser/zen-styles/zen-media-controls.css (../../zen/media/zen-media-controls.css)
content/browser/zen-components/ZenDownloadAnimation.mjs (../../zen/downloads/ZenDownloadAnimation.mjs)
content/browser/zen-styles/zen-download-arc-animation.css (../../zen/downloads/zen-download-arc-animation.css)
content/browser/zen-styles/zen-download-box-animation.css (../../zen/downloads/zen-download-box-animation.css)
# Images
content/browser/zen-images/brand-header.svg (../../zen/images/brand-header.svg)
content/browser/zen-images/layouts/collapsed.png (../../zen/images/layouts/collapsed.png)
content/browser/zen-images/layouts/multiple-toolbar.png (../../zen/images/layouts/multiple-toolbar.png)
content/browser/zen-images/layouts/single-toolbar.png (../../zen/images/layouts/single-toolbar.png)
content/browser/zen-images/grain-bg.png (../../zen/images/grain-bg.png)
content/browser/zen-images/note-indicator.svg (../../zen/images/note-indicator.svg)
content/browser/zen-images/downloads/download.svg (../../zen/images/downloads/download.svg)
content/browser/zen-images/downloads/archive.svg (../../zen/images/downloads/archive.svg)
# Fonts
content/browser/zen-fonts/JunicodeVF-Italic.woff2 (../../zen/fonts/JunicodeVF-Italic.woff2)
content/browser/zen-fonts/JunicodeVF-Roman.woff2 (../../zen/fonts/JunicodeVF-Roman.woff2)
# JS Vendor
content/browser/zen-vendor/tsparticles.confetti.bundle.min.js (../../zen/vendor/tsparticles.confetti.bundle.min.js)
content/browser/zen-vendor/motion.min.mjs (../../zen/vendor/motion.min.mjs)
# FavIcons for startup
content/browser/zen-images/favicons/calendar.svg (../../zen/images/favicons/calendar.svg)
content/browser/zen-images/favicons/discord.svg (../../zen/images/favicons/discord.svg)
content/browser/zen-images/favicons/figma.svg (../../zen/images/favicons/figma.svg)
content/browser/zen-images/favicons/github.svg (../../zen/images/favicons/github.svg)
content/browser/zen-images/favicons/notion.svg (../../zen/images/favicons/notion.svg)
content/browser/zen-images/favicons/obsidian.svg (../../zen/images/favicons/obsidian.svg)
content/browser/zen-images/favicons/slack.svg (../../zen/images/favicons/slack.svg)
content/browser/zen-images/favicons/reddit.svg (../../zen/images/favicons/reddit.svg)
content/browser/zen-images/favicons/x.svg (../../zen/images/favicons/x.svg)
content/browser/zen-images/favicons/trello.svg (../../zen/images/favicons/trello.svg)
#include ../../../zen/common/jar.inc.mn
#include ../../../zen/compact-mode/jar.inc.mn
#include ../../../zen/split-view/jar.inc.mn
#include ../../../zen/mods/jar.inc.mn
#include ../../../zen/workspaces/jar.inc.mn
#include ../../../zen/tabs/jar.inc.mn
#include ../../../zen/kbs/jar.inc.mn
#include ../../../zen/glance/jar.inc.mn
#include ../../../zen/folders/jar.inc.mn
#include ../../../zen/welcome/jar.inc.mn
#include ../../../zen/media/jar.inc.mn
#include ../../../zen/downloads/jar.inc.mn
#include ../../../zen/images/jar.inc.mn
#include ../../../zen/vendor/jar.inc.mn
#include ../../../zen/fonts/jar.inc.mn

View File

@@ -6,11 +6,11 @@
# the window is fully loaded.
# Make sure they are loaded before the global-scripts.inc file.
<script type="text/javascript" src="chrome://browser/content/zen-sets.js"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenHasPolyfill.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenCommonUtils.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenKeyboardShortcuts.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenWorkspaceIcons.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenWorkspace.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenWorkspaces.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenWorkspacesSync.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenSessionStore.mjs"></script>
<script type="module" src="chrome://browser/content/zen-components/ZenKeyboardShortcuts.mjs"></script>
<script type="module" src="chrome://browser/content/zen-components/ZenHasPolyfill.mjs"></script>
<script type="module" src="chrome://browser/content/zen-components/ZenSessionStore.mjs"></script>
<script type="module" src="chrome://browser/content/zen-components/ZenWorkspaces.mjs"></script>
<script type="module" src="chrome://browser/content/zen-components/ZenWorkspace.mjs"></script>
<script type="module" src="chrome://browser/content/zen-components/ZenWorkspaceIcons.mjs"></script>

View File

@@ -1,8 +1,13 @@
/* eslint-disable no-undef */
/* eslint-disable no-undef, no-unused-vars */
// 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/.
const { nsZenMultiWindowFeature } = ChromeUtils.importESModule(
'chrome://browser/content/zen-components/ZenCommonUtils.mjs',
{ global: 'current' }
);
var gZenMarketplaceManager = {
async init() {
const checkForUpdates = document.getElementById('zenThemeMarketplaceCheckForUpdates');
@@ -634,7 +639,6 @@ var gZenMarketplaceManager = {
const kZenExtendedSidebar = 'zen.view.sidebar-expanded';
const kZenSingleToolbar = 'zen.view.use-single-toolbar';
/* eslint-disable no-unused-vars */
var gZenLooksAndFeel = {
init() {
if (this.__hasInitialized) return;
@@ -696,7 +700,6 @@ var gZenLooksAndFeel = {
},
};
/* eslint-disable no-unused-vars */
var gZenWorkspacesSettings = {
init() {
var tabsUnloaderPrefListener = {
@@ -751,7 +754,7 @@ const ZEN_CKS_WRAPPER_ID = `${ZEN_CKS_CLASS_BASE}-wrapper`;
const ZEN_CKS_GROUP_PREFIX = `${ZEN_CKS_CLASS_BASE}-group`;
const KEYBIND_ATTRIBUTE_KEY = 'key';
var zenMissingKeyboardShortcutL10n = {
const zenMissingKeyboardShortcutL10n = {
key_quickRestart: 'zen-key-quick-restart',
key_delete: 'zen-key-delete',
goBackKb: 'zen-key-go-back',
@@ -805,7 +808,6 @@ var zenIgnoreKeyboardShortcutL10n = [
'zen-full-zoom-reduce-shortcut-alt-a',
];
/* eslint-disable no-unused-vars */
var gZenCKSSettings = {
async init() {
await this._initializeCKS();

View File

@@ -2,7 +2,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/.
<script src="chrome://browser/content/zen-components/ZenKeyboardShortcuts.mjs"/>
<script type="module" src="chrome://browser/content/zen-components/ZenKeyboardShortcuts.mjs"/>
<html:template id="template-paneZenCKS">
<hbox id="ZenCKSCategory"
class="subcategory"

View File

@@ -2,7 +2,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/.
<script src="chrome://browser/content/preferences/zen-settings.js"/>
<script type="text/javascript" src="chrome://browser/content/preferences/zen-settings.js"/>
<html:template id="template-paneZenLooks">
<hbox id="zenVerticalTabsCategory"

View File

@@ -2,7 +2,6 @@
# 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/.
<script src="chrome://browser/content/zen-components/ZenCommonUtils.mjs" defer=""/>
<html:template id="template-paneZenMarketplace">
<hbox id="ZenMarketplaceCategory"
class="subcategory"

View File

@@ -1,12 +1,12 @@
diff --git a/browser/components/tabbrowser/AsyncTabSwitcher.sys.mjs b/browser/components/tabbrowser/AsyncTabSwitcher.sys.mjs
index bcd7689e9d68ef8b171c327188174334c4271e21..f69180acb87644f109aa91b871e347f1b1835f53 100644
index bcd7689e9d68ef8b171c327188174334c4271e21..0a95e1137fdf4b63e0d841776ad934da1a513c6f 100644
--- a/browser/components/tabbrowser/AsyncTabSwitcher.sys.mjs
+++ b/browser/components/tabbrowser/AsyncTabSwitcher.sys.mjs
@@ -938,6 +938,7 @@ export class AsyncTabSwitcher {
this.tabbrowser._printPreviewBrowsers.has(browser) ||
this.tabbrowser.splitViewBrowsers.includes(browser) ||
lazy.PictureInPicture.isOriginatingBrowser(browser)
+ || browser?.parentNode?.parentNode?.parentNode?.classList?.contains("zen-glance-background")
+ || browser?.zenModeActive
);
}

View File

@@ -1,8 +1,16 @@
diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js
index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326cbd973686 100644
index c0eafd4faf8d57b8486c5bf8917375850ec8147e..cead9e6e52f7354e20b8b64ad06a075e6923fe5f 100644
--- a/browser/components/tabbrowser/content/tabbrowser.js
+++ b/browser/components/tabbrowser/content/tabbrowser.js
@@ -450,15 +450,64 @@
@@ -386,6 +386,7 @@
* @type {MozBrowser[]}
*/
get splitViewBrowsers() {
+ return gZenViewSplitter.splitViewBrowsers;
const browsers = [];
if (this.#activeSplitView) {
for (const tab of this.#activeSplitView.tabs) {
@@ -450,15 +451,64 @@
return this.tabContainer.visibleTabs;
}
@@ -69,7 +77,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
set selectedTab(val) {
if (
gSharedTabWarning.willShowSharedTabWarning(val) ||
@@ -613,6 +662,7 @@
@@ -613,6 +663,7 @@
this.tabpanels.appendChild(panel);
let tab = this.tabs[0];
@@ -77,7 +85,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
tab.linkedPanel = uniqueId;
this._selectedTab = tab;
this._selectedBrowser = browser;
@@ -898,13 +948,17 @@
@@ -898,13 +949,17 @@
}
this.showTab(aTab);
@@ -96,7 +104,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
aTab.setAttribute("pinned", "true");
this._updateTabBarForPinnedTabs();
@@ -917,11 +971,15 @@
@@ -917,11 +972,15 @@
}
this.#handleTabMove(aTab, () => {
@@ -113,7 +121,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
});
aTab.style.marginInlineStart = "";
@@ -1098,6 +1156,8 @@
@@ -1098,6 +1157,8 @@
let LOCAL_PROTOCOLS = ["chrome:", "about:", "resource:", "data:"];
@@ -122,7 +130,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
if (
aIconURL &&
!LOCAL_PROTOCOLS.some(protocol => aIconURL.startsWith(protocol))
@@ -1107,6 +1167,9 @@
@@ -1107,6 +1168,9 @@
);
return;
}
@@ -132,7 +140,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
let browser = this.getBrowserForTab(aTab);
browser.mIconURL = aIconURL;
@@ -1379,7 +1442,6 @@
@@ -1379,7 +1443,6 @@
// Preview mode should not reset the owner
if (!this._previewMode && !oldTab.selected) {
@@ -140,7 +148,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
}
let lastRelatedTab = this._lastRelatedTabMap.get(oldTab);
@@ -1470,6 +1532,7 @@
@@ -1470,6 +1533,7 @@
if (!this._previewMode) {
newTab.recordTimeFromUnloadToReload();
newTab.updateLastAccessed();
@@ -148,7 +156,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
oldTab.updateLastAccessed();
// if this is the foreground window, update the last-seen timestamps.
if (this.ownerGlobal == BrowserWindowTracker.getTopWindow()) {
@@ -1622,6 +1685,9 @@
@@ -1622,6 +1686,9 @@
}
let activeEl = document.activeElement;
@@ -158,7 +166,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
// If focus is on the old tab, move it to the new tab.
if (activeEl == oldTab) {
newTab.focus();
@@ -1945,7 +2011,8 @@
@@ -1945,7 +2012,8 @@
}
_setTabLabel(aTab, aLabel, { beforeTabOpen, isContentTitle, isURL } = {}) {
@@ -168,7 +176,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
return false;
}
@@ -2053,7 +2120,7 @@
@@ -2053,7 +2121,7 @@
newIndex = this.selectedTab._tPos + 1;
}
@@ -177,7 +185,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
if (this.isTabGroupLabel(targetTab)) {
throw new Error(
"Replacing a tab group label with a tab is not supported"
@@ -2328,6 +2395,7 @@
@@ -2328,6 +2396,7 @@
uriIsAboutBlank,
userContextId,
skipLoad,
@@ -185,7 +193,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
} = {}) {
let b = document.createXULElement("browser");
// Use the JSM global to create the permanentKey, so that if the
@@ -2401,8 +2469,7 @@
@@ -2401,8 +2470,7 @@
// we use a different attribute name for this?
b.setAttribute("name", name);
}
@@ -195,7 +203,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
b.setAttribute("transparent", "true");
}
@@ -2567,7 +2634,7 @@
@@ -2567,7 +2635,7 @@
let panel = this.getPanel(browser);
let uniqueId = this._generateUniquePanelID();
@@ -204,7 +212,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
aTab.linkedPanel = uniqueId;
// Inject the <browser> into the DOM if necessary.
@@ -2626,8 +2693,8 @@
@@ -2626,8 +2694,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) {
@@ -215,7 +223,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
} else {
aTab.linkedBrowser.browsingContext.hasSiblings = this.tabs.length > 1;
}
@@ -2814,7 +2881,6 @@
@@ -2814,7 +2882,6 @@
this.selectedTab = this.addTrustedTab(BROWSER_NEW_TAB_URL, {
tabIndex: tab._tPos + 1,
userContextId: tab.userContextId,
@@ -223,7 +231,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
focusUrlBar: true,
});
resolve(this.selectedBrowser);
@@ -2923,6 +2989,8 @@
@@ -2923,6 +2990,8 @@
schemelessInput,
hasValidUserGestureActivation = false,
textDirectiveUserActivation = false,
@@ -232,7 +240,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
} = {}
) {
// all callers of addTab that pass a params object need to pass
@@ -2933,10 +3001,17 @@
@@ -2933,10 +3002,17 @@
);
}
@@ -250,7 +258,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
// If we're opening a foreground tab, set the owner by default.
ownerTab ??= inBackground ? null : this.selectedTab;
@@ -2944,6 +3019,7 @@
@@ -2944,6 +3020,7 @@
if (this.selectedTab.owner) {
this.selectedTab.owner = null;
}
@@ -258,7 +266,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
// Find the tab that opened this one, if any. This is used for
// determining positioning, and inherited attributes such as the
@@ -2996,6 +3072,19 @@
@@ -2996,6 +3073,19 @@
noInitialLabel,
skipBackgroundNotify,
});
@@ -278,7 +286,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
if (insertTab) {
// Insert the tab into the tab container in the correct position.
this.#insertTabAtIndex(t, {
@@ -3004,6 +3093,7 @@
@@ -3004,6 +3094,7 @@
ownerTab,
openerTab,
pinned,
@@ -286,7 +294,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
bulkOrderedOpen,
tabGroup: tabGroup ?? openerTab?.group,
});
@@ -3022,6 +3112,7 @@
@@ -3022,6 +3113,7 @@
openWindowInfo,
skipLoad,
triggeringRemoteType,
@@ -294,7 +302,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
}));
if (focusUrlBar) {
@@ -3146,6 +3237,12 @@
@@ -3146,6 +3238,12 @@
}
}
@@ -307,7 +315,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
// Additionally send pinned tab events
if (pinned) {
this.#notifyPinnedStatus(t);
@@ -3330,10 +3427,10 @@
@@ -3330,10 +3428,10 @@
isAdoptingGroup = false,
isUserTriggered = false,
telemetryUserCreateSource = "unknown",
@@ -319,7 +327,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
}
if (!color) {
@@ -3354,9 +3451,14 @@
@@ -3354,9 +3452,14 @@
label,
isAdoptingGroup
);
@@ -336,7 +344,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
);
group.addTabs(tabs);
@@ -3477,7 +3579,7 @@
@@ -3477,7 +3580,7 @@
}
this.#handleTabMove(tab, () =>
@@ -345,7 +353,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
);
}
@@ -3679,6 +3781,7 @@
@@ -3679,6 +3782,7 @@
openWindowInfo,
skipLoad,
triggeringRemoteType,
@@ -353,7 +361,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
}
) {
// If we don't have a preferred remote type (or it is `NOT_REMOTE`), and
@@ -3748,6 +3851,7 @@
@@ -3748,6 +3852,7 @@
openWindowInfo,
name,
skipLoad,
@@ -361,7 +369,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
});
}
@@ -3935,7 +4039,7 @@
@@ -3935,7 +4040,7 @@
// Add a new tab if needed.
if (!tab) {
let createLazyBrowser =
@@ -370,7 +378,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
let url = "about:blank";
if (tabData.entries?.length) {
@@ -3972,8 +4076,10 @@
@@ -3972,8 +4077,10 @@
insertTab: false,
skipLoad: true,
preferredRemoteType,
@@ -382,7 +390,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
if (select) {
tabToSelect = tab;
}
@@ -3985,7 +4091,8 @@
@@ -3985,7 +4092,8 @@
this.pinTab(tab);
// Then ensure all the tab open/pinning information is sent.
this._fireTabOpen(tab, {});
@@ -392,7 +400,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
let { groupId } = tabData;
const tabGroup = tabGroupWorkingData.get(groupId);
// if a tab refers to a tab group we don't know, skip any group
@@ -3999,7 +4106,10 @@
@@ -3999,7 +4107,10 @@
tabGroup.stateData.id,
tabGroup.stateData.color,
tabGroup.stateData.collapsed,
@@ -404,7 +412,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
);
tabsFragment.appendChild(tabGroup.node);
}
@@ -4044,9 +4154,23 @@
@@ -4044,9 +4155,23 @@
// to remove the old selected tab.
if (tabToSelect) {
let leftoverTab = this.selectedTab;
@@ -428,7 +436,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
if (tabs.length > 1 || !tabs[0].selected) {
this._updateTabsAfterInsert();
@@ -4237,11 +4361,14 @@
@@ -4237,11 +4362,14 @@
if (ownerTab) {
tab.owner = ownerTab;
}
@@ -444,7 +452,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
if (
!bulkOrderedOpen &&
((openerTab &&
@@ -4253,7 +4380,7 @@
@@ -4253,7 +4381,7 @@
let lastRelatedTab =
openerTab && this._lastRelatedTabMap.get(openerTab);
let previousTab = lastRelatedTab || openerTab || this.selectedTab;
@@ -453,7 +461,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
tabGroup = previousTab.group;
}
if (
@@ -4264,7 +4391,7 @@
@@ -4264,7 +4392,7 @@
) {
elementIndex = Infinity;
} else if (previousTab.visible) {
@@ -462,7 +470,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
} else if (previousTab == FirefoxViewHandler.tab) {
elementIndex = 0;
}
@@ -4292,14 +4419,14 @@
@@ -4292,14 +4420,14 @@
}
// Ensure index is within bounds.
if (tab.pinned) {
@@ -481,7 +489,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
if (pinned && !itemAfter?.pinned) {
itemAfter = null;
@@ -4310,7 +4437,7 @@
@@ -4310,7 +4438,7 @@
this.tabContainer._invalidateCachedTabs();
@@ -490,7 +498,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
if (this.isTab(itemAfter) && itemAfter.group == tabGroup) {
// Place at the front of, or between tabs in, the same tab group
this.tabContainer.insertBefore(tab, itemAfter);
@@ -4338,7 +4465,11 @@
@@ -4338,7 +4466,11 @@
const tabContainer = pinned
? this.tabContainer.pinnedTabsContainer
: this.tabContainer;
@@ -502,7 +510,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
}
this._updateTabsAfterInsert();
@@ -4346,6 +4477,7 @@
@@ -4346,6 +4478,7 @@
if (pinned) {
this._updateTabBarForPinnedTabs();
}
@@ -510,7 +518,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
TabBarVisibility.update();
}
@@ -4635,6 +4767,9 @@
@@ -4635,6 +4768,9 @@
return;
}
@@ -520,7 +528,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
this.removeTabs(selectedTabs, { isUserTriggered, telemetrySource });
}
@@ -4896,6 +5031,7 @@
@@ -4896,6 +5032,7 @@
telemetrySource,
} = {}
) {
@@ -528,7 +536,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
// When 'closeWindowWithLastTab' pref is enabled, closing all tabs
// can be considered equivalent to closing the window.
if (
@@ -4985,6 +5121,7 @@
@@ -4985,6 +5122,7 @@
if (lastToClose) {
this.removeTab(lastToClose, aParams);
}
@@ -536,7 +544,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
} catch (e) {
console.error(e);
}
@@ -5023,6 +5160,12 @@
@@ -5023,6 +5161,12 @@
aTab._closeTimeNoAnimTimerId = Glean.browserTabclose.timeNoAnim.start();
}
@@ -549,7 +557,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
// Handle requests for synchronously removing an already
// asynchronously closing tab.
if (!animate && aTab.closing) {
@@ -5037,6 +5180,9 @@
@@ -5037,6 +5181,9 @@
// state).
let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width;
let isLastTab = this.#isLastTabInWindow(aTab);
@@ -559,7 +567,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
if (
!this._beginRemoveTab(aTab, {
closeWindowFastpath: true,
@@ -5085,7 +5231,13 @@
@@ -5085,7 +5232,13 @@
// We're not animating, so we can cancel the animation stopwatch.
Glean.browserTabclose.timeAnim.cancel(aTab._closeTimeAnimTimerId);
aTab._closeTimeAnimTimerId = null;
@@ -574,7 +582,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
return;
}
@@ -5219,7 +5371,7 @@
@@ -5219,7 +5372,7 @@
closeWindowWithLastTab != null
? closeWindowWithLastTab
: !window.toolbar.visible ||
@@ -583,7 +591,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
if (closeWindow) {
// We've already called beforeunload on all the relevant tabs if we get here,
@@ -5243,6 +5395,7 @@
@@ -5243,6 +5396,7 @@
newTab = true;
}
@@ -591,7 +599,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
aTab._endRemoveArgs = [closeWindow, newTab];
// swapBrowsersAndCloseOther will take care of closing the window without animation.
@@ -5283,13 +5436,7 @@
@@ -5283,13 +5437,7 @@
aTab._mouseleave();
if (newTab) {
@@ -606,7 +614,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
} else {
TabBarVisibility.update();
}
@@ -5422,6 +5569,7 @@
@@ -5422,6 +5570,7 @@
this.tabs[i]._tPos = i;
}
@@ -614,7 +622,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
if (!this._windowIsClosing) {
// update tab close buttons state
this.tabContainer._updateCloseButtons();
@@ -5643,6 +5791,7 @@
@@ -5643,6 +5792,7 @@
}
let excludeTabs = new Set(aExcludeTabs);
@@ -622,7 +630,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
// If this tab has a successor, it should be selectable, since
// hiding or closing a tab removes that tab as a successor.
@@ -5655,13 +5804,13 @@
@@ -5655,13 +5805,13 @@
!excludeTabs.has(aTab.owner) &&
Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose")
) {
@@ -638,7 +646,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
);
let tab = this.tabContainer.findNextTab(aTab, {
@@ -5677,7 +5826,7 @@
@@ -5677,7 +5827,7 @@
}
if (tab) {
@@ -647,7 +655,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
}
// If no qualifying visible tab was found, see if there is a tab in
@@ -5698,7 +5847,7 @@
@@ -5698,7 +5848,7 @@
});
}
@@ -656,7 +664,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
}
_blurTab(aTab) {
@@ -6104,10 +6253,10 @@
@@ -6104,10 +6254,10 @@
SessionStore.deleteCustomTabValue(aTab, "hiddenBy");
}
@@ -669,7 +677,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
aTab.selected ||
aTab.closing ||
// Tabs that are sharing the screen, microphone or camera cannot be hidden.
@@ -6166,6 +6315,7 @@
@@ -6166,6 +6316,7 @@
* @param {MozTabbrowserTab|MozTabbrowserTabGroup|MozTabbrowserTabGroup.labelElement} aTab
*/
replaceTabWithWindow(aTab, aOptions) {
@@ -677,7 +685,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
if (this.tabs.length == 1) {
return null;
}
@@ -6299,7 +6449,7 @@
@@ -6299,7 +6450,7 @@
* `true` if element is a `<tab-group>`
*/
isTabGroup(element) {
@@ -686,7 +694,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
}
/**
@@ -6375,8 +6525,8 @@
@@ -6375,8 +6526,8 @@
}
// Don't allow mixing pinned and unpinned tabs.
@@ -697,7 +705,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
} else {
tabIndex = Math.max(tabIndex, this.pinnedTabCount);
}
@@ -6402,10 +6552,16 @@
@@ -6402,10 +6553,16 @@
this.#handleTabMove(
element,
() => {
@@ -716,7 +724,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
if (neighbor && this.isTab(element) && tabIndex > element._tPos) {
neighbor.after(element);
} else {
@@ -6463,23 +6619,28 @@
@@ -6463,23 +6620,28 @@
#moveTabNextTo(element, targetElement, moveBefore = false, metricsContext) {
if (this.isTabGroupLabel(targetElement)) {
targetElement = targetElement.group;
@@ -751,7 +759,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
} 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
@@ -6492,14 +6653,34 @@
@@ -6492,14 +6654,34 @@
// 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.
@@ -787,7 +795,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
element.pinned
? this.tabContainer.pinnedTabsContainer
: this.tabContainer;
@@ -6508,7 +6689,7 @@
@@ -6508,7 +6690,7 @@
element,
() => {
if (moveBefore) {
@@ -796,7 +804,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
} else if (targetElement) {
targetElement.after(element);
} else {
@@ -6580,10 +6761,10 @@
@@ -6580,10 +6762,10 @@
* @param {TabMetricsContext} [metricsContext]
*/
moveTabToGroup(aTab, aGroup, metricsContext) {
@@ -809,7 +817,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
return;
}
if (aTab.group && aTab.group.id === aGroup.id) {
@@ -6613,6 +6794,7 @@
@@ -6613,6 +6795,7 @@
let state = {
tabIndex: tab._tPos,
@@ -817,7 +825,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
};
if (tab.visible) {
state.elementIndex = tab.elementIndex;
@@ -6639,7 +6821,7 @@
@@ -6639,7 +6822,7 @@
let changedTabGroup =
previousTabState.tabGroupId != currentTabState.tabGroupId;
@@ -826,7 +834,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
tab.dispatchEvent(
new CustomEvent("TabMove", {
bubbles: true,
@@ -6676,6 +6858,10 @@
@@ -6676,6 +6859,10 @@
moveActionCallback();
@@ -837,7 +845,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
// Clear tabs cache after moving nodes because the order of tabs may have
// changed.
this.tabContainer._invalidateCachedTabs();
@@ -7576,7 +7762,7 @@
@@ -7576,7 +7763,7 @@
// preventDefault(). It will still raise the window if appropriate.
break;
}
@@ -846,7 +854,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
window.focus();
aEvent.preventDefault();
break;
@@ -7593,7 +7779,6 @@
@@ -7593,7 +7780,6 @@
}
case "TabGroupCollapse":
aEvent.target.tabs.forEach(tab => {
@@ -854,7 +862,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
});
break;
case "TabGroupCreateByUser":
@@ -8542,6 +8727,7 @@
@@ -8542,6 +8728,7 @@
aWebProgress.isTopLevel
) {
this.mTab.setAttribute("busy", "true");
@@ -862,7 +870,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
gBrowser._tabAttrModified(this.mTab, ["busy"]);
this.mTab._notselectedsinceload = !this.mTab.selected;
}
@@ -9543,7 +9729,7 @@ var TabContextMenu = {
@@ -9543,7 +9730,7 @@ var TabContextMenu = {
);
contextUnpinSelectedTabs.hidden =
!this.contextTab.pinned || !this.multiselected;
@@ -871,7 +879,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
// Build Ask Chat items
TabContextMenu.GenAI.buildTabMenu(
document.getElementById("context_askChat"),
@@ -9863,6 +10049,7 @@ var TabContextMenu = {
@@ -9863,6 +10050,7 @@ var TabContextMenu = {
)
);
} else {

View File

@@ -0,0 +1,15 @@
diff --git a/browser/components/urlbar/UrlbarResult.sys.mjs b/browser/components/urlbar/UrlbarResult.sys.mjs
index 0882c0a01d17184cadb56aa1236ca97adf7f866b..4a5842eda6280205b96f9aee9b6f3b49fac7077c 100644
--- a/browser/components/urlbar/UrlbarResult.sys.mjs
+++ b/browser/components/urlbar/UrlbarResult.sys.mjs
@@ -172,6 +172,10 @@ export class UrlbarResult {
return this.#heuristic;
}
+ set heuristic(value) {
+ this.#heuristic = value;
+ }
+
get hideRowLabel() {
return this.#hideRowLabel;
}

View File

@@ -0,0 +1,73 @@
# 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/.
# Note: You'll need to be on the root directory of the repo to run this script:
# python3 src/browser/themes/shared/zen-icons/check_unused_icons.py
import os
import sys
import argparse
IGNORE_DIRS = ['node_modules', 'engine']
def get_all_icon_files(icon_dir):
icon_files = []
for root, _, files in os.walk(icon_dir):
for file in files:
if file.endswith('.svg'):
icon_files.append(file)
return icon_files
def find_icon_usage(icon_files):
used_icons = set()
for root, _, files in os.walk('src'):
if any(ignored in root for ignored in IGNORE_DIRS):
continue
for file in files:
# ignore jar files
if file.endswith(('.mn')):
continue
try:
with open(os.path.join(root, file), 'r', encoding='utf-8') as f:
content = f.read()
for icon in icon_files:
if icon in content:
used_icons.add(icon)
except BaseException:
continue
return used_icons
def main(args):
parser = argparse.ArgumentParser(description='Check for unused zen icons.')
parser.add_argument('--remove', action='store_true', help='Remove unused icons')
parsed_args = parser.parse_args(args)
icon_dir = 'src/browser/themes/shared/zen-icons/lin'
icon_files = get_all_icon_files(icon_dir)
used_icons = find_icon_usage(icon_files)
unused_icons = set(icon_files) - used_icons
if unused_icons:
print("Unused icons:")
for icon in sorted(unused_icons):
if parsed_args.remove:
os.remove(os.path.join(icon_dir, icon))
print(f"Removed {icon}")
else:
print(icon)
else:
print("No unused icons found.")
if parsed_args.remove:
print("Unused icons removed.")
os.chdir('src/browser/themes/shared/zen-icons')
os.system("sh ./update-resources.sh")
if __name__ == "__main__":
main(sys.argv[1:])

View File

@@ -3,13 +3,10 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifdef XP_WIN
* skin/classic/browser/zen-icons/accessibility.svg (../shared/zen-icons/lin/accessibility.svg)
* skin/classic/browser/zen-icons/add-to-dictionary.svg (../shared/zen-icons/lin/add-to-dictionary.svg)
* skin/classic/browser/zen-icons/arrow-down.svg (../shared/zen-icons/lin/arrow-down.svg)
* skin/classic/browser/zen-icons/arrow-left.svg (../shared/zen-icons/lin/arrow-left.svg)
* skin/classic/browser/zen-icons/arrow-right.svg (../shared/zen-icons/lin/arrow-right.svg)
* skin/classic/browser/zen-icons/arrow-up.svg (../shared/zen-icons/lin/arrow-up.svg)
* skin/classic/browser/zen-icons/audio-save.svg (../shared/zen-icons/lin/audio-save.svg)
* skin/classic/browser/zen-icons/autoplay-media-blocked.svg (../shared/zen-icons/lin/autoplay-media-blocked.svg)
* skin/classic/browser/zen-icons/autoplay-media-fill.svg (../shared/zen-icons/lin/autoplay-media-fill.svg)
* skin/classic/browser/zen-icons/autoplay-media.svg (../shared/zen-icons/lin/autoplay-media.svg)
@@ -22,9 +19,7 @@
* skin/classic/browser/zen-icons/camera.svg (../shared/zen-icons/lin/camera.svg)
* skin/classic/browser/zen-icons/canvas-blocked.svg (../shared/zen-icons/lin/canvas-blocked.svg)
* skin/classic/browser/zen-icons/canvas.svg (../shared/zen-icons/lin/canvas.svg)
* skin/classic/browser/zen-icons/checkmark.svg (../shared/zen-icons/lin/checkmark.svg)
* skin/classic/browser/zen-icons/chevron.svg (../shared/zen-icons/lin/chevron.svg)
* skin/classic/browser/zen-icons/close-all.svg (../shared/zen-icons/lin/close-all.svg)
* skin/classic/browser/zen-icons/close.svg (../shared/zen-icons/lin/close.svg)
* skin/classic/browser/zen-icons/container-tab.svg (../shared/zen-icons/lin/container-tab.svg)
* skin/classic/browser/zen-icons/cookies-fill.svg (../shared/zen-icons/lin/cookies-fill.svg)
@@ -41,20 +36,14 @@
* skin/classic/browser/zen-icons/edit-cut.svg (../shared/zen-icons/lin/edit-cut.svg)
* skin/classic/browser/zen-icons/edit-delete.svg (../shared/zen-icons/lin/edit-delete.svg)
* skin/classic/browser/zen-icons/edit-paste.svg (../shared/zen-icons/lin/edit-paste.svg)
* skin/classic/browser/zen-icons/edit-redo.svg (../shared/zen-icons/lin/edit-redo.svg)
* skin/classic/browser/zen-icons/edit-select-all.svg (../shared/zen-icons/lin/edit-select-all.svg)
* skin/classic/browser/zen-icons/edit-theme.svg (../shared/zen-icons/lin/edit-theme.svg)
* skin/classic/browser/zen-icons/edit-undo.svg (../shared/zen-icons/lin/edit-undo.svg)
* skin/classic/browser/zen-icons/edit.svg (../shared/zen-icons/lin/edit.svg)
* skin/classic/browser/zen-icons/essential-add.svg (../shared/zen-icons/lin/essential-add.svg)
* skin/classic/browser/zen-icons/essential-remove.svg (../shared/zen-icons/lin/essential-remove.svg)
* skin/classic/browser/zen-icons/expand-sidebar.svg (../shared/zen-icons/lin/expand-sidebar.svg)
* skin/classic/browser/zen-icons/ext-link.svg (../shared/zen-icons/lin/ext-link.svg)
* skin/classic/browser/zen-icons/extension-blocked.svg (../shared/zen-icons/lin/extension-blocked.svg)
* skin/classic/browser/zen-icons/extension-fill.svg (../shared/zen-icons/lin/extension-fill.svg)
* skin/classic/browser/zen-icons/extension.svg (../shared/zen-icons/lin/extension.svg)
* skin/classic/browser/zen-icons/face-sun.svg (../shared/zen-icons/lin/face-sun.svg)
* skin/classic/browser/zen-icons/firefox.svg (../shared/zen-icons/lin/firefox.svg)
* skin/classic/browser/zen-icons/folder.svg (../shared/zen-icons/lin/folder.svg)
* skin/classic/browser/zen-icons/forget.svg (../shared/zen-icons/lin/forget.svg)
* skin/classic/browser/zen-icons/forward.svg (../shared/zen-icons/lin/forward.svg)
@@ -63,28 +52,21 @@
* skin/classic/browser/zen-icons/geo-blocked.svg (../shared/zen-icons/lin/geo-blocked.svg)
* skin/classic/browser/zen-icons/geo-fill.svg (../shared/zen-icons/lin/geo-fill.svg)
* skin/classic/browser/zen-icons/geo.svg (../shared/zen-icons/lin/geo.svg)
* skin/classic/browser/zen-icons/heart-circle-fill.svg (../shared/zen-icons/lin/heart-circle-fill.svg)
* skin/classic/browser/zen-icons/help.svg (../shared/zen-icons/lin/help.svg)
* skin/classic/browser/zen-icons/history.svg (../shared/zen-icons/lin/history.svg)
* skin/classic/browser/zen-icons/home.svg (../shared/zen-icons/lin/home.svg)
* skin/classic/browser/zen-icons/image-copy.svg (../shared/zen-icons/lin/image-copy.svg)
* skin/classic/browser/zen-icons/image-open.svg (../shared/zen-icons/lin/image-open.svg)
* skin/classic/browser/zen-icons/image-save.svg (../shared/zen-icons/lin/image-save.svg)
* skin/classic/browser/zen-icons/info.svg (../shared/zen-icons/lin/info.svg)
* skin/classic/browser/zen-icons/inspect.svg (../shared/zen-icons/lin/inspect.svg)
* skin/classic/browser/zen-icons/library.svg (../shared/zen-icons/lin/library.svg)
* skin/classic/browser/zen-icons/link.svg (../shared/zen-icons/lin/link.svg)
* skin/classic/browser/zen-icons/mail.svg (../shared/zen-icons/lin/mail.svg)
* skin/classic/browser/zen-icons/manage.svg (../shared/zen-icons/lin/manage.svg)
* skin/classic/browser/zen-icons/media-loop.svg (../shared/zen-icons/lin/media-loop.svg)
* skin/classic/browser/zen-icons/media-mute.svg (../shared/zen-icons/lin/media-mute.svg)
* skin/classic/browser/zen-icons/media-next.svg (../shared/zen-icons/lin/media-next.svg)
* skin/classic/browser/zen-icons/media-pause.svg (../shared/zen-icons/lin/media-pause.svg)
* skin/classic/browser/zen-icons/media-pip.svg (../shared/zen-icons/lin/media-pip.svg)
* skin/classic/browser/zen-icons/media-play.svg (../shared/zen-icons/lin/media-play.svg)
* skin/classic/browser/zen-icons/media-previous.svg (../shared/zen-icons/lin/media-previous.svg)
* skin/classic/browser/zen-icons/media-speed.svg (../shared/zen-icons/lin/media-speed.svg)
* skin/classic/browser/zen-icons/media-unmute.svg (../shared/zen-icons/lin/media-unmute.svg)
* skin/classic/browser/zen-icons/menu-bar.svg (../shared/zen-icons/lin/menu-bar.svg)
* skin/classic/browser/zen-icons/menu.svg (../shared/zen-icons/lin/menu.svg)
* skin/classic/browser/zen-icons/microphone-blocked-fill.svg (../shared/zen-icons/lin/microphone-blocked-fill.svg)
* skin/classic/browser/zen-icons/microphone-blocked.svg (../shared/zen-icons/lin/microphone-blocked.svg)
@@ -92,13 +74,11 @@
* skin/classic/browser/zen-icons/microphone.svg (../shared/zen-icons/lin/microphone.svg)
* skin/classic/browser/zen-icons/midi.svg (../shared/zen-icons/lin/midi.svg)
* skin/classic/browser/zen-icons/moon-stars.svg (../shared/zen-icons/lin/moon-stars.svg)
* skin/classic/browser/zen-icons/move-tab.svg (../shared/zen-icons/lin/move-tab.svg)
* skin/classic/browser/zen-icons/new-tab-image.svg (../shared/zen-icons/lin/new-tab-image.svg)
* skin/classic/browser/zen-icons/open.svg (../shared/zen-icons/lin/open.svg)
* skin/classic/browser/zen-icons/page-portrait.svg (../shared/zen-icons/lin/page-portrait.svg)
* skin/classic/browser/zen-icons/palette.svg (../shared/zen-icons/lin/palette.svg)
* skin/classic/browser/zen-icons/passwords.svg (../shared/zen-icons/lin/passwords.svg)
* skin/classic/browser/zen-icons/paste-and-go.svg (../shared/zen-icons/lin/paste-and-go.svg)
* skin/classic/browser/zen-icons/permissions-fill.svg (../shared/zen-icons/lin/permissions-fill.svg)
* skin/classic/browser/zen-icons/permissions.svg (../shared/zen-icons/lin/permissions.svg)
* skin/classic/browser/zen-icons/persistent-storage-blocked.svg (../shared/zen-icons/lin/persistent-storage-blocked.svg)
@@ -113,7 +93,6 @@
* skin/classic/browser/zen-icons/privateBrowsing.svg (../shared/zen-icons/lin/privateBrowsing.svg)
* skin/classic/browser/zen-icons/reader-mode.svg (../shared/zen-icons/lin/reader-mode.svg)
* skin/classic/browser/zen-icons/reload.svg (../shared/zen-icons/lin/reload.svg)
* skin/classic/browser/zen-icons/report.svg (../shared/zen-icons/lin/report.svg)
* skin/classic/browser/zen-icons/save.svg (../shared/zen-icons/lin/save.svg)
* skin/classic/browser/zen-icons/screen-blocked.svg (../shared/zen-icons/lin/screen-blocked.svg)
* skin/classic/browser/zen-icons/screen.svg (../shared/zen-icons/lin/screen.svg)
@@ -130,7 +109,6 @@
* skin/classic/browser/zen-icons/sidebar-right.svg (../shared/zen-icons/lin/sidebar-right.svg)
* skin/classic/browser/zen-icons/sidebar.svg (../shared/zen-icons/lin/sidebar.svg)
* skin/classic/browser/zen-icons/sidebars-right.svg (../shared/zen-icons/lin/sidebars-right.svg)
* skin/classic/browser/zen-icons/source-code.svg (../shared/zen-icons/lin/source-code.svg)
* skin/classic/browser/zen-icons/sparkles.svg (../shared/zen-icons/lin/sparkles.svg)
* skin/classic/browser/zen-icons/spell-check.svg (../shared/zen-icons/lin/spell-check.svg)
* skin/classic/browser/zen-icons/split.svg (../shared/zen-icons/lin/split.svg)
@@ -146,23 +124,17 @@
* skin/classic/browser/zen-icons/unpin.svg (../shared/zen-icons/lin/unpin.svg)
* skin/classic/browser/zen-icons/video-blocked-fill.svg (../shared/zen-icons/lin/video-blocked-fill.svg)
* skin/classic/browser/zen-icons/video-fill.svg (../shared/zen-icons/lin/video-fill.svg)
* skin/classic/browser/zen-icons/video-open.svg (../shared/zen-icons/lin/video-open.svg)
* skin/classic/browser/zen-icons/video-save.svg (../shared/zen-icons/lin/video-save.svg)
* skin/classic/browser/zen-icons/window.svg (../shared/zen-icons/lin/window.svg)
* skin/classic/browser/zen-icons/xr-blocked.svg (../shared/zen-icons/lin/xr-blocked.svg)
* skin/classic/browser/zen-icons/xr-fill.svg (../shared/zen-icons/lin/xr-fill.svg)
* skin/classic/browser/zen-icons/xr.svg (../shared/zen-icons/lin/xr.svg)
* skin/classic/browser/zen-icons/zoom-control.svg (../shared/zen-icons/lin/zoom-control.svg)
* skin/classic/browser/zen-icons/zoom-out.svg (../shared/zen-icons/lin/zoom-out.svg)
#endif
#ifdef XP_MACOSX
* skin/classic/browser/zen-icons/accessibility.svg (../shared/zen-icons/lin/accessibility.svg)
* skin/classic/browser/zen-icons/add-to-dictionary.svg (../shared/zen-icons/lin/add-to-dictionary.svg)
* skin/classic/browser/zen-icons/arrow-down.svg (../shared/zen-icons/lin/arrow-down.svg)
* skin/classic/browser/zen-icons/arrow-left.svg (../shared/zen-icons/lin/arrow-left.svg)
* skin/classic/browser/zen-icons/arrow-right.svg (../shared/zen-icons/lin/arrow-right.svg)
* skin/classic/browser/zen-icons/arrow-up.svg (../shared/zen-icons/lin/arrow-up.svg)
* skin/classic/browser/zen-icons/audio-save.svg (../shared/zen-icons/lin/audio-save.svg)
* skin/classic/browser/zen-icons/autoplay-media-blocked.svg (../shared/zen-icons/lin/autoplay-media-blocked.svg)
* skin/classic/browser/zen-icons/autoplay-media-fill.svg (../shared/zen-icons/lin/autoplay-media-fill.svg)
* skin/classic/browser/zen-icons/autoplay-media.svg (../shared/zen-icons/lin/autoplay-media.svg)
@@ -175,9 +147,7 @@
* skin/classic/browser/zen-icons/camera.svg (../shared/zen-icons/lin/camera.svg)
* skin/classic/browser/zen-icons/canvas-blocked.svg (../shared/zen-icons/lin/canvas-blocked.svg)
* skin/classic/browser/zen-icons/canvas.svg (../shared/zen-icons/lin/canvas.svg)
* skin/classic/browser/zen-icons/checkmark.svg (../shared/zen-icons/lin/checkmark.svg)
* skin/classic/browser/zen-icons/chevron.svg (../shared/zen-icons/lin/chevron.svg)
* skin/classic/browser/zen-icons/close-all.svg (../shared/zen-icons/lin/close-all.svg)
* skin/classic/browser/zen-icons/close.svg (../shared/zen-icons/lin/close.svg)
* skin/classic/browser/zen-icons/container-tab.svg (../shared/zen-icons/lin/container-tab.svg)
* skin/classic/browser/zen-icons/cookies-fill.svg (../shared/zen-icons/lin/cookies-fill.svg)
@@ -194,20 +164,14 @@
* skin/classic/browser/zen-icons/edit-cut.svg (../shared/zen-icons/lin/edit-cut.svg)
* skin/classic/browser/zen-icons/edit-delete.svg (../shared/zen-icons/lin/edit-delete.svg)
* skin/classic/browser/zen-icons/edit-paste.svg (../shared/zen-icons/lin/edit-paste.svg)
* skin/classic/browser/zen-icons/edit-redo.svg (../shared/zen-icons/lin/edit-redo.svg)
* skin/classic/browser/zen-icons/edit-select-all.svg (../shared/zen-icons/lin/edit-select-all.svg)
* skin/classic/browser/zen-icons/edit-theme.svg (../shared/zen-icons/lin/edit-theme.svg)
* skin/classic/browser/zen-icons/edit-undo.svg (../shared/zen-icons/lin/edit-undo.svg)
* skin/classic/browser/zen-icons/edit.svg (../shared/zen-icons/lin/edit.svg)
* skin/classic/browser/zen-icons/essential-add.svg (../shared/zen-icons/lin/essential-add.svg)
* skin/classic/browser/zen-icons/essential-remove.svg (../shared/zen-icons/lin/essential-remove.svg)
* skin/classic/browser/zen-icons/expand-sidebar.svg (../shared/zen-icons/lin/expand-sidebar.svg)
* skin/classic/browser/zen-icons/ext-link.svg (../shared/zen-icons/lin/ext-link.svg)
* skin/classic/browser/zen-icons/extension-blocked.svg (../shared/zen-icons/lin/extension-blocked.svg)
* skin/classic/browser/zen-icons/extension-fill.svg (../shared/zen-icons/lin/extension-fill.svg)
* skin/classic/browser/zen-icons/extension.svg (../shared/zen-icons/lin/extension.svg)
* skin/classic/browser/zen-icons/face-sun.svg (../shared/zen-icons/lin/face-sun.svg)
* skin/classic/browser/zen-icons/firefox.svg (../shared/zen-icons/lin/firefox.svg)
* skin/classic/browser/zen-icons/folder.svg (../shared/zen-icons/lin/folder.svg)
* skin/classic/browser/zen-icons/forget.svg (../shared/zen-icons/lin/forget.svg)
* skin/classic/browser/zen-icons/forward.svg (../shared/zen-icons/lin/forward.svg)
@@ -216,28 +180,21 @@
* skin/classic/browser/zen-icons/geo-blocked.svg (../shared/zen-icons/lin/geo-blocked.svg)
* skin/classic/browser/zen-icons/geo-fill.svg (../shared/zen-icons/lin/geo-fill.svg)
* skin/classic/browser/zen-icons/geo.svg (../shared/zen-icons/lin/geo.svg)
* skin/classic/browser/zen-icons/heart-circle-fill.svg (../shared/zen-icons/lin/heart-circle-fill.svg)
* skin/classic/browser/zen-icons/help.svg (../shared/zen-icons/lin/help.svg)
* skin/classic/browser/zen-icons/history.svg (../shared/zen-icons/lin/history.svg)
* skin/classic/browser/zen-icons/home.svg (../shared/zen-icons/lin/home.svg)
* skin/classic/browser/zen-icons/image-copy.svg (../shared/zen-icons/lin/image-copy.svg)
* skin/classic/browser/zen-icons/image-open.svg (../shared/zen-icons/lin/image-open.svg)
* skin/classic/browser/zen-icons/image-save.svg (../shared/zen-icons/lin/image-save.svg)
* skin/classic/browser/zen-icons/info.svg (../shared/zen-icons/lin/info.svg)
* skin/classic/browser/zen-icons/inspect.svg (../shared/zen-icons/lin/inspect.svg)
* skin/classic/browser/zen-icons/library.svg (../shared/zen-icons/lin/library.svg)
* skin/classic/browser/zen-icons/link.svg (../shared/zen-icons/lin/link.svg)
* skin/classic/browser/zen-icons/mail.svg (../shared/zen-icons/lin/mail.svg)
* skin/classic/browser/zen-icons/manage.svg (../shared/zen-icons/lin/manage.svg)
* skin/classic/browser/zen-icons/media-loop.svg (../shared/zen-icons/lin/media-loop.svg)
* skin/classic/browser/zen-icons/media-mute.svg (../shared/zen-icons/lin/media-mute.svg)
* skin/classic/browser/zen-icons/media-next.svg (../shared/zen-icons/lin/media-next.svg)
* skin/classic/browser/zen-icons/media-pause.svg (../shared/zen-icons/lin/media-pause.svg)
* skin/classic/browser/zen-icons/media-pip.svg (../shared/zen-icons/lin/media-pip.svg)
* skin/classic/browser/zen-icons/media-play.svg (../shared/zen-icons/lin/media-play.svg)
* skin/classic/browser/zen-icons/media-previous.svg (../shared/zen-icons/lin/media-previous.svg)
* skin/classic/browser/zen-icons/media-speed.svg (../shared/zen-icons/lin/media-speed.svg)
* skin/classic/browser/zen-icons/media-unmute.svg (../shared/zen-icons/lin/media-unmute.svg)
* skin/classic/browser/zen-icons/menu-bar.svg (../shared/zen-icons/lin/menu-bar.svg)
* skin/classic/browser/zen-icons/menu.svg (../shared/zen-icons/lin/menu.svg)
* skin/classic/browser/zen-icons/microphone-blocked-fill.svg (../shared/zen-icons/lin/microphone-blocked-fill.svg)
* skin/classic/browser/zen-icons/microphone-blocked.svg (../shared/zen-icons/lin/microphone-blocked.svg)
@@ -245,13 +202,11 @@
* skin/classic/browser/zen-icons/microphone.svg (../shared/zen-icons/lin/microphone.svg)
* skin/classic/browser/zen-icons/midi.svg (../shared/zen-icons/lin/midi.svg)
* skin/classic/browser/zen-icons/moon-stars.svg (../shared/zen-icons/lin/moon-stars.svg)
* skin/classic/browser/zen-icons/move-tab.svg (../shared/zen-icons/lin/move-tab.svg)
* skin/classic/browser/zen-icons/new-tab-image.svg (../shared/zen-icons/lin/new-tab-image.svg)
* skin/classic/browser/zen-icons/open.svg (../shared/zen-icons/lin/open.svg)
* skin/classic/browser/zen-icons/page-portrait.svg (../shared/zen-icons/lin/page-portrait.svg)
* skin/classic/browser/zen-icons/palette.svg (../shared/zen-icons/lin/palette.svg)
* skin/classic/browser/zen-icons/passwords.svg (../shared/zen-icons/lin/passwords.svg)
* skin/classic/browser/zen-icons/paste-and-go.svg (../shared/zen-icons/lin/paste-and-go.svg)
* skin/classic/browser/zen-icons/permissions-fill.svg (../shared/zen-icons/lin/permissions-fill.svg)
* skin/classic/browser/zen-icons/permissions.svg (../shared/zen-icons/lin/permissions.svg)
* skin/classic/browser/zen-icons/persistent-storage-blocked.svg (../shared/zen-icons/lin/persistent-storage-blocked.svg)
@@ -266,7 +221,6 @@
* skin/classic/browser/zen-icons/privateBrowsing.svg (../shared/zen-icons/lin/privateBrowsing.svg)
* skin/classic/browser/zen-icons/reader-mode.svg (../shared/zen-icons/lin/reader-mode.svg)
* skin/classic/browser/zen-icons/reload.svg (../shared/zen-icons/lin/reload.svg)
* skin/classic/browser/zen-icons/report.svg (../shared/zen-icons/lin/report.svg)
* skin/classic/browser/zen-icons/save.svg (../shared/zen-icons/lin/save.svg)
* skin/classic/browser/zen-icons/screen-blocked.svg (../shared/zen-icons/lin/screen-blocked.svg)
* skin/classic/browser/zen-icons/screen.svg (../shared/zen-icons/lin/screen.svg)
@@ -283,7 +237,6 @@
* skin/classic/browser/zen-icons/sidebar-right.svg (../shared/zen-icons/lin/sidebar-right.svg)
* skin/classic/browser/zen-icons/sidebar.svg (../shared/zen-icons/lin/sidebar.svg)
* skin/classic/browser/zen-icons/sidebars-right.svg (../shared/zen-icons/lin/sidebars-right.svg)
* skin/classic/browser/zen-icons/source-code.svg (../shared/zen-icons/lin/source-code.svg)
* skin/classic/browser/zen-icons/sparkles.svg (../shared/zen-icons/lin/sparkles.svg)
* skin/classic/browser/zen-icons/spell-check.svg (../shared/zen-icons/lin/spell-check.svg)
* skin/classic/browser/zen-icons/split.svg (../shared/zen-icons/lin/split.svg)
@@ -299,23 +252,17 @@
* skin/classic/browser/zen-icons/unpin.svg (../shared/zen-icons/lin/unpin.svg)
* skin/classic/browser/zen-icons/video-blocked-fill.svg (../shared/zen-icons/lin/video-blocked-fill.svg)
* skin/classic/browser/zen-icons/video-fill.svg (../shared/zen-icons/lin/video-fill.svg)
* skin/classic/browser/zen-icons/video-open.svg (../shared/zen-icons/lin/video-open.svg)
* skin/classic/browser/zen-icons/video-save.svg (../shared/zen-icons/lin/video-save.svg)
* skin/classic/browser/zen-icons/window.svg (../shared/zen-icons/lin/window.svg)
* skin/classic/browser/zen-icons/xr-blocked.svg (../shared/zen-icons/lin/xr-blocked.svg)
* skin/classic/browser/zen-icons/xr-fill.svg (../shared/zen-icons/lin/xr-fill.svg)
* skin/classic/browser/zen-icons/xr.svg (../shared/zen-icons/lin/xr.svg)
* skin/classic/browser/zen-icons/zoom-control.svg (../shared/zen-icons/lin/zoom-control.svg)
* skin/classic/browser/zen-icons/zoom-out.svg (../shared/zen-icons/lin/zoom-out.svg)
#endif
#ifdef XP_LINUX
* skin/classic/browser/zen-icons/accessibility.svg (../shared/zen-icons/lin/accessibility.svg)
* skin/classic/browser/zen-icons/add-to-dictionary.svg (../shared/zen-icons/lin/add-to-dictionary.svg)
* skin/classic/browser/zen-icons/arrow-down.svg (../shared/zen-icons/lin/arrow-down.svg)
* skin/classic/browser/zen-icons/arrow-left.svg (../shared/zen-icons/lin/arrow-left.svg)
* skin/classic/browser/zen-icons/arrow-right.svg (../shared/zen-icons/lin/arrow-right.svg)
* skin/classic/browser/zen-icons/arrow-up.svg (../shared/zen-icons/lin/arrow-up.svg)
* skin/classic/browser/zen-icons/audio-save.svg (../shared/zen-icons/lin/audio-save.svg)
* skin/classic/browser/zen-icons/autoplay-media-blocked.svg (../shared/zen-icons/lin/autoplay-media-blocked.svg)
* skin/classic/browser/zen-icons/autoplay-media-fill.svg (../shared/zen-icons/lin/autoplay-media-fill.svg)
* skin/classic/browser/zen-icons/autoplay-media.svg (../shared/zen-icons/lin/autoplay-media.svg)
@@ -328,9 +275,7 @@
* skin/classic/browser/zen-icons/camera.svg (../shared/zen-icons/lin/camera.svg)
* skin/classic/browser/zen-icons/canvas-blocked.svg (../shared/zen-icons/lin/canvas-blocked.svg)
* skin/classic/browser/zen-icons/canvas.svg (../shared/zen-icons/lin/canvas.svg)
* skin/classic/browser/zen-icons/checkmark.svg (../shared/zen-icons/lin/checkmark.svg)
* skin/classic/browser/zen-icons/chevron.svg (../shared/zen-icons/lin/chevron.svg)
* skin/classic/browser/zen-icons/close-all.svg (../shared/zen-icons/lin/close-all.svg)
* skin/classic/browser/zen-icons/close.svg (../shared/zen-icons/lin/close.svg)
* skin/classic/browser/zen-icons/container-tab.svg (../shared/zen-icons/lin/container-tab.svg)
* skin/classic/browser/zen-icons/cookies-fill.svg (../shared/zen-icons/lin/cookies-fill.svg)
@@ -347,20 +292,14 @@
* skin/classic/browser/zen-icons/edit-cut.svg (../shared/zen-icons/lin/edit-cut.svg)
* skin/classic/browser/zen-icons/edit-delete.svg (../shared/zen-icons/lin/edit-delete.svg)
* skin/classic/browser/zen-icons/edit-paste.svg (../shared/zen-icons/lin/edit-paste.svg)
* skin/classic/browser/zen-icons/edit-redo.svg (../shared/zen-icons/lin/edit-redo.svg)
* skin/classic/browser/zen-icons/edit-select-all.svg (../shared/zen-icons/lin/edit-select-all.svg)
* skin/classic/browser/zen-icons/edit-theme.svg (../shared/zen-icons/lin/edit-theme.svg)
* skin/classic/browser/zen-icons/edit-undo.svg (../shared/zen-icons/lin/edit-undo.svg)
* skin/classic/browser/zen-icons/edit.svg (../shared/zen-icons/lin/edit.svg)
* skin/classic/browser/zen-icons/essential-add.svg (../shared/zen-icons/lin/essential-add.svg)
* skin/classic/browser/zen-icons/essential-remove.svg (../shared/zen-icons/lin/essential-remove.svg)
* skin/classic/browser/zen-icons/expand-sidebar.svg (../shared/zen-icons/lin/expand-sidebar.svg)
* skin/classic/browser/zen-icons/ext-link.svg (../shared/zen-icons/lin/ext-link.svg)
* skin/classic/browser/zen-icons/extension-blocked.svg (../shared/zen-icons/lin/extension-blocked.svg)
* skin/classic/browser/zen-icons/extension-fill.svg (../shared/zen-icons/lin/extension-fill.svg)
* skin/classic/browser/zen-icons/extension.svg (../shared/zen-icons/lin/extension.svg)
* skin/classic/browser/zen-icons/face-sun.svg (../shared/zen-icons/lin/face-sun.svg)
* skin/classic/browser/zen-icons/firefox.svg (../shared/zen-icons/lin/firefox.svg)
* skin/classic/browser/zen-icons/folder.svg (../shared/zen-icons/lin/folder.svg)
* skin/classic/browser/zen-icons/forget.svg (../shared/zen-icons/lin/forget.svg)
* skin/classic/browser/zen-icons/forward.svg (../shared/zen-icons/lin/forward.svg)
@@ -369,28 +308,21 @@
* skin/classic/browser/zen-icons/geo-blocked.svg (../shared/zen-icons/lin/geo-blocked.svg)
* skin/classic/browser/zen-icons/geo-fill.svg (../shared/zen-icons/lin/geo-fill.svg)
* skin/classic/browser/zen-icons/geo.svg (../shared/zen-icons/lin/geo.svg)
* skin/classic/browser/zen-icons/heart-circle-fill.svg (../shared/zen-icons/lin/heart-circle-fill.svg)
* skin/classic/browser/zen-icons/help.svg (../shared/zen-icons/lin/help.svg)
* skin/classic/browser/zen-icons/history.svg (../shared/zen-icons/lin/history.svg)
* skin/classic/browser/zen-icons/home.svg (../shared/zen-icons/lin/home.svg)
* skin/classic/browser/zen-icons/image-copy.svg (../shared/zen-icons/lin/image-copy.svg)
* skin/classic/browser/zen-icons/image-open.svg (../shared/zen-icons/lin/image-open.svg)
* skin/classic/browser/zen-icons/image-save.svg (../shared/zen-icons/lin/image-save.svg)
* skin/classic/browser/zen-icons/info.svg (../shared/zen-icons/lin/info.svg)
* skin/classic/browser/zen-icons/inspect.svg (../shared/zen-icons/lin/inspect.svg)
* skin/classic/browser/zen-icons/library.svg (../shared/zen-icons/lin/library.svg)
* skin/classic/browser/zen-icons/link.svg (../shared/zen-icons/lin/link.svg)
* skin/classic/browser/zen-icons/mail.svg (../shared/zen-icons/lin/mail.svg)
* skin/classic/browser/zen-icons/manage.svg (../shared/zen-icons/lin/manage.svg)
* skin/classic/browser/zen-icons/media-loop.svg (../shared/zen-icons/lin/media-loop.svg)
* skin/classic/browser/zen-icons/media-mute.svg (../shared/zen-icons/lin/media-mute.svg)
* skin/classic/browser/zen-icons/media-next.svg (../shared/zen-icons/lin/media-next.svg)
* skin/classic/browser/zen-icons/media-pause.svg (../shared/zen-icons/lin/media-pause.svg)
* skin/classic/browser/zen-icons/media-pip.svg (../shared/zen-icons/lin/media-pip.svg)
* skin/classic/browser/zen-icons/media-play.svg (../shared/zen-icons/lin/media-play.svg)
* skin/classic/browser/zen-icons/media-previous.svg (../shared/zen-icons/lin/media-previous.svg)
* skin/classic/browser/zen-icons/media-speed.svg (../shared/zen-icons/lin/media-speed.svg)
* skin/classic/browser/zen-icons/media-unmute.svg (../shared/zen-icons/lin/media-unmute.svg)
* skin/classic/browser/zen-icons/menu-bar.svg (../shared/zen-icons/lin/menu-bar.svg)
* skin/classic/browser/zen-icons/menu.svg (../shared/zen-icons/lin/menu.svg)
* skin/classic/browser/zen-icons/microphone-blocked-fill.svg (../shared/zen-icons/lin/microphone-blocked-fill.svg)
* skin/classic/browser/zen-icons/microphone-blocked.svg (../shared/zen-icons/lin/microphone-blocked.svg)
@@ -398,13 +330,11 @@
* skin/classic/browser/zen-icons/microphone.svg (../shared/zen-icons/lin/microphone.svg)
* skin/classic/browser/zen-icons/midi.svg (../shared/zen-icons/lin/midi.svg)
* skin/classic/browser/zen-icons/moon-stars.svg (../shared/zen-icons/lin/moon-stars.svg)
* skin/classic/browser/zen-icons/move-tab.svg (../shared/zen-icons/lin/move-tab.svg)
* skin/classic/browser/zen-icons/new-tab-image.svg (../shared/zen-icons/lin/new-tab-image.svg)
* skin/classic/browser/zen-icons/open.svg (../shared/zen-icons/lin/open.svg)
* skin/classic/browser/zen-icons/page-portrait.svg (../shared/zen-icons/lin/page-portrait.svg)
* skin/classic/browser/zen-icons/palette.svg (../shared/zen-icons/lin/palette.svg)
* skin/classic/browser/zen-icons/passwords.svg (../shared/zen-icons/lin/passwords.svg)
* skin/classic/browser/zen-icons/paste-and-go.svg (../shared/zen-icons/lin/paste-and-go.svg)
* skin/classic/browser/zen-icons/permissions-fill.svg (../shared/zen-icons/lin/permissions-fill.svg)
* skin/classic/browser/zen-icons/permissions.svg (../shared/zen-icons/lin/permissions.svg)
* skin/classic/browser/zen-icons/persistent-storage-blocked.svg (../shared/zen-icons/lin/persistent-storage-blocked.svg)
@@ -419,7 +349,6 @@
* skin/classic/browser/zen-icons/privateBrowsing.svg (../shared/zen-icons/lin/privateBrowsing.svg)
* skin/classic/browser/zen-icons/reader-mode.svg (../shared/zen-icons/lin/reader-mode.svg)
* skin/classic/browser/zen-icons/reload.svg (../shared/zen-icons/lin/reload.svg)
* skin/classic/browser/zen-icons/report.svg (../shared/zen-icons/lin/report.svg)
* skin/classic/browser/zen-icons/save.svg (../shared/zen-icons/lin/save.svg)
* skin/classic/browser/zen-icons/screen-blocked.svg (../shared/zen-icons/lin/screen-blocked.svg)
* skin/classic/browser/zen-icons/screen.svg (../shared/zen-icons/lin/screen.svg)
@@ -436,7 +365,6 @@
* skin/classic/browser/zen-icons/sidebar-right.svg (../shared/zen-icons/lin/sidebar-right.svg)
* skin/classic/browser/zen-icons/sidebar.svg (../shared/zen-icons/lin/sidebar.svg)
* skin/classic/browser/zen-icons/sidebars-right.svg (../shared/zen-icons/lin/sidebars-right.svg)
* skin/classic/browser/zen-icons/source-code.svg (../shared/zen-icons/lin/source-code.svg)
* skin/classic/browser/zen-icons/sparkles.svg (../shared/zen-icons/lin/sparkles.svg)
* skin/classic/browser/zen-icons/spell-check.svg (../shared/zen-icons/lin/spell-check.svg)
* skin/classic/browser/zen-icons/split.svg (../shared/zen-icons/lin/split.svg)
@@ -452,13 +380,10 @@
* skin/classic/browser/zen-icons/unpin.svg (../shared/zen-icons/lin/unpin.svg)
* skin/classic/browser/zen-icons/video-blocked-fill.svg (../shared/zen-icons/lin/video-blocked-fill.svg)
* skin/classic/browser/zen-icons/video-fill.svg (../shared/zen-icons/lin/video-fill.svg)
* skin/classic/browser/zen-icons/video-open.svg (../shared/zen-icons/lin/video-open.svg)
* skin/classic/browser/zen-icons/video-save.svg (../shared/zen-icons/lin/video-save.svg)
* skin/classic/browser/zen-icons/window.svg (../shared/zen-icons/lin/window.svg)
* skin/classic/browser/zen-icons/xr-blocked.svg (../shared/zen-icons/lin/xr-blocked.svg)
* skin/classic/browser/zen-icons/xr-fill.svg (../shared/zen-icons/lin/xr-fill.svg)
* skin/classic/browser/zen-icons/xr.svg (../shared/zen-icons/lin/xr.svg)
* skin/classic/browser/zen-icons/zoom-control.svg (../shared/zen-icons/lin/zoom-control.svg)
* skin/classic/browser/zen-icons/zoom-out.svg (../shared/zen-icons/lin/zoom-out.svg)
#endif
* skin/classic/browser/zen-icons/urlbar-arrow.svg (../shared/zen-icons/common/urlbar-arrow.svg)

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><circle cx="9" cy="2.25" r="1.5" data-color="color-2"></circle><line x1="7.25" y1="16.5" x2="7.25" y2="6.24"></line><line x1="10.75" y1="6.24" x2="10.75" y2="16.5"></line><path d="M2.75,5.75c1.751,.3,3.86,.531,6.25,.531,1.777,0,3.894-.128,6.25-.531"></path><line x1="7.25" y1="11.25" x2="10.75" y2="11.25"></line></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><path d="M14.181,3.257c-.221-.865-.998-1.507-1.931-1.507H5.75c-1.105,0-2,.896-2,2v12.5l5.25-3.5,5.25,3.5v-3"></path><line x1="14.25" y1="5.75" x2="14.25" y2="10.75" data-color="color-2"></line><line x1="16.75" y1="8.25" x2="11.75" y2="8.25" data-color="color-2"></line></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><line x1="5.75" y1="7.25" x2="5.75" y2="13.75"></line><line x1="14.75" y1="5.75" x2="14.75" y2="12.25"></line><path d="m8.6399,3.0186l4.9461-.8246c.61-.102,1.164.368,1.164.986v2.57l-9,1.5"></path><circle cx="3.75" cy="13.75" r="2"></circle><circle cx="12.75" cy="12.25" r="2"></circle><line x1="3.75" y1="1.25" x2="3.75" y2="6.25" data-color="color-2"></line><line x1="6.25" y1="3.75" x2="1.25" y2="3.75" data-color="color-2"></line></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><polyline points="2.75 9.5 6.5 13.25 15.25 4.5"></polyline></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><path d="M1.75,16.25v-.5c0-1.105,.895-2,2-2H14.25c1.105,0,2,.895,2,2v.5"></path><path d="M3.75,11.25c0-.828,.672-1.5,1.5-1.5h7.5c.828,0,1.5,.672,1.5,1.5"></path><polyline points="11.5 4.75 9 7.25 6.5 4.75" data-color="color-2"></polyline><line x1="9" y1="7" x2="9" y2="1.75" data-color="color-2"></line></g></svg>

View File

@@ -2,4 +2,4 @@
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><line x1="14" y1="4" x2="4" y2="14" data-color="color-2"></line><line x1="4" y1="4" x2="14" y2="14"></line></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="2" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><line x1="14" y1="4" x2="4" y2="14" data-color="color-2"></line><line x1="4" y1="4" x2="14" y2="14"></line></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><path d="M15,10c-.528-.461-2.7-2.251-6-2.251s-5.472,1.79-6,2.251" data-color="color-2"></path><polyline points="13.375 5.598 15 10 10.47 11.222"></polyline></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><line x1="14.75" y1=".75" x2="14.75" y2="5.75" data-color="color-2"></line><line x1="17.25" y1="3.25" x2="12.25" y2="3.25" data-color="color-2"></line><path d="M2.25,5.25c0-1.105,.895-2,2-2"></path><path d="M14.75,13.75c0,1.105-.895,2-2,2"></path><path d="M4.25,15.75c-1.105,0-2-.895-2-2"></path><line x1="7.25" y1="3.25" x2="9.25" y2="3.25"></line><line x1="7.25" y1="15.75" x2="9.75" y2="15.75"></line><line x1="14.75" y1="8.75" x2="14.75" y2="10.75"></line><line x1="2.25" y1="8.25" x2="2.25" y2="10.75"></line></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><path d="M3,10c.528-.461,2.7-2.251,6-2.251s5.472,1.79,6,2.251" data-color="color-2"></path><polyline points="4.625 5.598 3 10 7.53 11.222"></polyline></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><path d="M2.75,15.25s3.599-.568,4.546-1.515c.947-.947,7.327-7.327,7.327-7.327,.837-.837,.837-2.194,0-3.03-.837-.837-2.194-.837-3.03,0,0,0-6.38,6.38-7.327,7.327s-1.515,4.546-1.515,4.546h0Z"></path></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><path d="M4.25,9.25V3.75c0-1.105,.895-2,2-2h6c1.105,0,2,.895,2,2V13.25c0,1.105-.895,2-2,2H7.25"></path><polyline points="7.24 6.75 11.25 6.75 11.25 10.76" data-color="color-2"></polyline><line x1="11.25" y1="6.75" x2="1.75" y2="16.25" data-color="color-2"></line></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg id="a" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" fill-opacity="context-fill-opacity"><path d="M14.7498,13.0913c-.0154.9253-.7896,1.6587-1.715,1.6587h-6.956c-.2705,0-.4541-.275-.3505-.5248l.0024-.0057c.4574-1.1044,1.1996-2.0362,2.1473-2.7161.1179-.0846.2601-.1284.4052-.1284h4.7793c.9416,0,1.703.7711,1.6873,1.7163Z"/><path d="M9.9212,1.25c.2705,0,.4541.275.3505.5248l-.0024.0057c-.4574,1.1044-1.1996,2.0362-2.1473,2.7161-.1179.0846-.2601.1284-.4052.1284H2.9653c-.9254,0-1.6996-.7334-1.715-1.6587-.0158-.9452.7457-1.7163,1.6873-1.7163h6.9837Z"/><path d="M2.9372,14.75c-.2152,0-.4339-.0414-.6451-.1289-.861-.3566-1.2699-1.3437-.9132-2.2047.5485-1.3241,1.3346-2.5112,2.3367-3.5283,1.0381-1.0537,2.2623-1.877,3.6387-2.4471,1.8919-.7837,3.3654-2.2571,4.149-4.149.3566-.861,1.3437-1.2698,2.2047-.9132.861.3566,1.2699,1.3437.9132,2.2047-.5485,1.3241-1.3346,2.5112-2.3367,3.5283-1.0381,1.0537-2.2623,1.877-3.6387,2.4471-1.8919.7837-3.3654,2.2571-4.149,4.149-.2691.6498-.8975,1.0421-1.5596,1.0421Z"/></svg>

View File

@@ -0,0 +1,5 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g fill="context-fill" fill-opacity="context-fill-opacity" class="nc-icon-wrapper"><path d="M9 1C13.4183 1 17 4.58172 17 9C17 13.4183 13.4183 17 9 17C4.58172 17 1 13.4183 1 9C1 4.58172 4.58172 1 9 1ZM10.7285 5.55176C10.0566 5.5598 9.42663 5.86058 9 6.36914C8.57267 5.86121 7.94219 5.56042 7.26758 5.55176C6.01248 5.55999 4.99539 6.58541 5 7.83789C5 10.5743 7.79989 12.25 8.6582 12.6982C8.76478 12.7542 8.88246 12.7812 8.99902 12.7812C9.11561 12.7812 9.2339 12.7535 9.33984 12.6982C10.1978 12.2503 12.9989 10.5754 12.999 7.83887C13.0037 6.58553 11.9872 5.55909 10.7285 5.55176Z"/></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><path d="M6.587,12.243l5.206-5.2c.391-.391,1.024-.391,1.414,0l3.043,3.043" data-color="color-2"></path><path d="M1.75,6.75v6.5c0,1.105,.895,2,2,2H12.25" data-color="color-2"></path><rect x="4.75" y="2.75" width="11.5" height="9.5" rx="2" ry="2" transform="translate(21 15) rotate(180)"></rect><path d="M8,7c-.551,0-1-.449-1-1s.449-1,1-1,1,.449,1,1-.449,1-1,1Z" fill="currentColor" data-color="color-2" data-stroke="none" stroke="none"></path></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><path d="M4,15.25l5.836-5.836c.781-.781,2.047-.781,2.828,0l3.086,3.086" data-color="color-2"></path><rect x="2.25" y="4.75" width="13.5" height="10.5" rx="2" ry="2"></rect><line x1="4.75" y1="1.75" x2="13.25" y2="1.75" data-color="color-2"></line><circle cx="5.75" cy="8.25" r="1.25" fill="currentColor" data-color="color-2" data-stroke="none" stroke="none"></circle></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><path d="m3.762,14.989l6.074-6.075c.781-.781,2.047-.781,2.828,0l2.586,2.586"></path><circle cx="6.25" cy="7.25" r="1.25" stroke-width="0" fill="currentColor"></circle><line x1="14.25" y1="1.25" x2="14.25" y2="6.25" data-color="color-2"></line><path d="m9.461,2.75h-4.711c-1.1046,0-2,.8955-2,2v8.5c0,1.1045.8954,2,2,2h8.5c1.1046,0,2-.8955,2-2v-4.7109"></path><line x1="16.75" y1="3.75" x2="11.75" y2="3.75" data-color="color-2"></line></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><polyline points="14 6.25 16.25 4 14 1.75" data-color="color-2"></polyline><path d="M6.596,2.75h-1.846c-1.105,0-2,.896-2,2V13.25c0,1.104,.895,2,2,2H13.25c1.105,0,2-.896,2-2v-4.846"></path><polyline points="11 6.25 8.75 4 11 1.75" data-color="color-2"></polyline></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><path d="M5,13.75h-.75c-1.105,0-2-.895-2-2V6.25c0-1.105,.895-2,2-2H13.75c1.105,0,2,.895,2,2v5.5c0,1.105-.895,2-2,2h-5.742" data-color="color-2"></path><polyline points="10.5 11.25 8.008 13.742 10.5 16.235"></polyline></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><path d="M5.75,12.25h-2c-1.105,0-2-.895-2-2V5.75c0-1.105,.895-2,2-2H12.25c1.105,0,2,.895,2,2v2"></path><rect x="8.75" y="10.75" width="7.5" height="4.5" rx="1.5" ry="1.5"></rect><polyline points="7.25 6.25 7.25 9.25 4.25 9.25" data-color="color-2"></polyline><line x1="7.25" y1="9.25" x2="4.25" y2="6.25" data-color="color-2"></line></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><circle cx="9" cy="12" r="1" fill="currentColor" data-color="color-2"></circle><path d="M12.75,12.25h3.487c.003-.083,.013-.166,.013-.25,0-4.004-3.246-7.25-7.25-7.25S1.75,7.996,1.75,12c0,.084,.01,.167,.013,.25h3.487"></path><line x1="8.495" y1="11.137" x2="6.557" y2="7.827" data-color="color-2"></line></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><circle cx="9" cy="9" r=".5" fill="currentColor" data-color="color-2"></circle><circle cx="9" cy="3.25" r=".5" fill="currentColor"></circle><circle cx="9" cy="14.75" r=".5" fill="currentColor"></circle></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><rect x="11.25" y="10.75" width="5" height="5" rx="1.5" ry="1.5" data-color="color-2"></rect><rect x="11.25" y="2.25" width="5" height="5" rx="1.5" ry="1.5"></rect><polyline points="6.75 11.5 9 13.75 6.75 16"></polyline><path d="M9,13.75h-2.5c-2.623,0-4.75-2.127-4.75-4.75h0c0-2.623,2.127-4.75,4.75-4.75h1.75"></path></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><path d="M6.25,2.75h-1c-1.105,0-2,.895-2,2V14.25c0,1.105,.895,2,2,2h7.5c1.105,0,2-.895,2-2V4.75c0-1.105-.895-2-2-2h-1"></path><rect x="6.25" y="1.25" width="5.5" height="3" rx="1" ry="1" data-color="color-2"></rect><polyline points="6.25 10.25 8 12.25 11.75 7.25" data-color="color-2"></polyline></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><path d="M7.638,3.495L2.213,12.891c-.605,1.048,.151,2.359,1.362,2.359H14.425c1.211,0,1.967-1.31,1.362-2.359L10.362,3.495c-.605-1.048-2.119-1.048-2.724,0Z"></path><line x1="9" y1="6.5" x2="9" y2="10" data-color="color-2"></line><path d="M9,13.569c-.552,0-1-.449-1-1s.448-1,1-1,1,.449,1,1-.448,1-1,1Z" fill="currentColor" data-color="color-2" data-stroke="none" stroke="none"></path></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><polyline points="5.25 13.25 1.75 9 5.25 4.75"></polyline><polyline points="12.75 13.25 16.25 9 12.75 4.75"></polyline><line x1="7.75" y1="13.25" x2="10.25" y2="4.75" data-color="color-2"></line></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><path d="M12.211,6.984l-2.296-1.385c-.402-.243-.915,.047-.915,.516v2.771c0,.47,.513,.759,.915,.516l2.296-1.385c.389-.235,.389-.798,0-1.033Z" fill="currentColor" data-color="color-2" data-stroke="none" stroke="none"></path><path d="M1.75,6.75v6.5c0,1.105,.895,2,2,2H12.25" data-color="color-2"></path><rect x="4.75" y="2.75" width="11.5" height="9.5" rx="2" ry="2" transform="translate(21 15) rotate(180)"></rect></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><path d="M2.25,8.75V4.75c0-1.105,.895-2,2-2h1.951c.607,0,1.18,.275,1.56,.748l.603,.752h5.386c1.105,0,2,.895,2,2v2.844"></path><path d="M15.75,10.313v-1.563c0-1.104-.895-2-2-2H4.25c-1.105,0-2,.896-2,2v4.5c0,1.104,.895,2,2,2h5"></path><path d="M12.539,11.323l4.204,2.477c.343,.202,.343,.697,0,.899l-4.204,2.477c-.349,.206-.789-.045-.789-.449v-4.955c0-.404,.441-.655,.789-.449Z" data-color="color-2"></path></g></svg>

View File

@@ -1,5 +0,0 @@
#filter dumbComments emptyLines substitution
# 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/.
<svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 18 18"><g stroke-linecap="round" stroke-width="1.5" fill="none" stroke="context-fill" stroke-opacity="context-fill-opacity" stroke-linejoin="round" class="nc-icon-wrapper"><circle cx="7.75" cy="7.75" r="5"></circle><line x1="15.25" y1="15.25" x2="11.285" y2="11.285"></line><circle cx="5.5" cy="7.25" r=".75" fill="currentColor" data-color="color-2" data-stroke="none" stroke="none"></circle><circle cx="10" cy="7.25" r=".75" fill="currentColor" data-color="color-2" data-stroke="none" stroke="none"></circle><path d="M6.75,8.5h2c.276,0,.5,.224,.5,.5h0c0,.828-.672,1.5-1.5,1.5h0c-.828,0-1.5-.672-1.5-1.5h0c0-.276,.224-.5,.5-.5Z" fill="currentColor" data-color="color-2" data-stroke="none" stroke="none"></path></g></svg>

View File

@@ -1,77 +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/.
{
class nsHasPolyfill {
constructor() {
this.observers = [];
this.idStore = 0;
}
/**
* @param {{selector: string, exists: boolean}} descendantSelectors
*/
observeSelectorExistence(element, descendantSelectors, stateAttribute, attributeFilter = []) {
const updateState = () => {
const exists = descendantSelectors.some(({ selector }) => {
let selected = element.querySelector(selector);
if (selected?.tagName?.toLowerCase() === 'menu') {
return null;
}
return selected;
});
const { exists: shouldExist = true } = descendantSelectors;
if (exists === shouldExist) {
if (!element.hasAttribute(stateAttribute)) {
gZenCompactModeManager._setElementExpandAttribute(element, true, stateAttribute);
}
} else {
if (element.hasAttribute(stateAttribute)) {
gZenCompactModeManager._setElementExpandAttribute(element, false, stateAttribute);
}
}
};
const observer = new MutationObserver(updateState);
updateState();
const observerId = this.idStore++;
this.observers.push({
id: observerId,
observer,
element,
attributeFilter,
});
return observerId;
}
disconnectObserver(observerId) {
const index = this.observers.findIndex((o) => o.id === observerId);
if (index !== -1) {
this.observers[index].observer.disconnect();
}
}
connectObserver(observerId) {
const observer = this.observers.find((o) => o.id === observerId);
if (observer) {
observer.observer.observe(observer.element, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: observer.attributeFilter.length ? observer.attributeFilter : undefined,
});
}
}
destroy() {
this.observers.forEach((observer) => observer.observer.disconnect());
this.observers = [];
}
}
const hasPolyfillInstance = new nsHasPolyfill();
window.addEventListener('unload', () => hasPolyfillInstance.destroy(), { once: true });
window.ZenHasPolyfill = hasPolyfillInstance;
}

View File

@@ -5,5 +5,5 @@
// prettier-ignore
{
Services.scriptloader.loadSubScript("chrome://browser/content/ZenStartup.mjs", this);
ChromeUtils.importESModule("chrome://browser/content/ZenStartup.mjs", { global: "current" });
}

View File

@@ -1,46 +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/.
{
class ZenSessionStore extends nsZenPreloadedFeature {
init() {
this.#waitAndCleanup();
}
promiseInitialized = new Promise((resolve) => {
this._resolveInitialized = resolve;
});
restoreInitialTabData(tab, tabData) {
if (tabData.zenWorkspace) {
tab.setAttribute('zen-workspace-id', tabData.zenWorkspace);
}
if (tabData.zenPinnedId) {
tab.setAttribute('zen-pin-id', tabData.zenPinnedId);
}
if (tabData.zenHasStaticLabel) {
tab.setAttribute('zen-has-static-label', 'true');
}
if (tabData.zenEssential) {
tab.setAttribute('zen-essential', 'true');
}
if (tabData.zenDefaultUserContextId) {
tab.setAttribute('zenDefaultUserContextId', 'true');
}
if (tabData.zenPinnedEntry) {
tab.setAttribute('zen-pinned-entry', tabData.zenPinnedEntry);
}
}
async #waitAndCleanup() {
await SessionStore.promiseInitialized;
this.#cleanup();
}
#cleanup() {
this._resolveInitialized();
}
}
window.gZenSessionStore = new ZenSessionStore();
}

View File

@@ -1,227 +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/.
{
var gZenStartup = new (class {
#watermarkIgnoreElements = ['zen-toast-container'];
#hasInitializedLayout = false;
isReady = false;
async init() {
// important: We do this to ensure that some firefox components
// are initialized before we start our own initialization.
// please, do not remove this line and if you do, make sure to
// test the startup process.
await new Promise((resolve) => setTimeout(resolve, 0));
this.openWatermark();
this.#initBrowserBackground();
this.#changeSidebarLocation();
this.#zenInitBrowserLayout();
}
#initBrowserBackground() {
const background = document.createXULElement('box');
background.id = 'zen-browser-background';
background.classList.add('zen-browser-generic-background');
const grain = document.createXULElement('box');
grain.classList.add('zen-browser-grain');
background.appendChild(grain);
document.getElementById('browser').prepend(background);
const toolbarBackground = background.cloneNode(true);
toolbarBackground.removeAttribute('id');
toolbarBackground.classList.add('zen-toolbar-background');
document.getElementById('titlebar').prepend(toolbarBackground);
}
#zenInitBrowserLayout() {
if (this.#hasInitializedLayout) return;
this.#hasInitializedLayout = true;
try {
const kNavbarItems = ['nav-bar', 'PersonalToolbar'];
const kNewContainerId = 'zen-appcontent-navbar-container';
let newContainer = document.getElementById(kNewContainerId);
for (let id of kNavbarItems) {
const node = document.getElementById(id);
console.assert(node, 'Could not find node with id: ' + id);
if (!node) continue;
newContainer.appendChild(node);
}
// Fix notification deck
const deckTemplate = document.getElementById('tab-notification-deck-template');
if (deckTemplate) {
document.getElementById('zen-appcontent-wrapper').prepend(deckTemplate);
}
gZenWorkspaces.init();
setTimeout(() => {
gZenUIManager.init();
this.#checkForWelcomePage();
}, 0);
} catch (e) {
console.error('ZenThemeModifier: Error initializing browser layout', e);
}
if (gBrowserInit.delayedStartupFinished) {
this.delayedStartupFinished();
} else {
Services.obs.addObserver(this, 'browser-delayed-startup-finished');
}
}
observe(aSubject, aTopic) {
// This nsIObserver method allows us to defer initialization until after
// this window has finished painting and starting up.
if (aTopic == 'browser-delayed-startup-finished' && aSubject == window) {
Services.obs.removeObserver(this, 'browser-delayed-startup-finished');
this.delayedStartupFinished();
}
}
delayedStartupFinished() {
gZenWorkspaces.promiseInitialized.then(async () => {
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')) {
gURLBar.focus();
}
// A bit of a hack to make sure the tabs toolbar is updated.
// Just in case we didn't get the right size.
gZenUIManager.updateTabsToolbar();
this.closeWatermark();
this.isReady = true;
});
}
openWatermark() {
if (!Services.prefs.getBoolPref('zen.watermark.enabled', false)) {
document.documentElement.removeAttribute('zen-before-loaded');
return;
}
for (let elem of document.querySelectorAll('#browser > *, #urlbar')) {
elem.style.opacity = 0;
}
}
closeWatermark() {
document.documentElement.removeAttribute('zen-before-loaded');
if (Services.prefs.getBoolPref('zen.watermark.enabled', false)) {
let elementsToIgnore = this.#watermarkIgnoreElements.map((id) => '#' + id).join(', ');
gZenUIManager.motion
.animate(
'#browser > *:not(' + elementsToIgnore + '), #urlbar, #tabbrowser-tabbox > *',
{
opacity: [0, 1],
},
{
duration: 0.1,
}
)
.then(() => {
for (let elem of document.querySelectorAll(
'#browser > *, #urlbar, #tabbrowser-tabbox > *'
)) {
elem.style.removeProperty('opacity');
}
});
}
window.requestAnimationFrame(() => {
window.dispatchEvent(new window.Event('resize')); // To recalculate the layout
});
}
#changeSidebarLocation() {
const kElementsToAppend = ['sidebar-splitter', 'sidebar-box'];
const browser = document.getElementById('browser');
browser.prepend(gNavToolbox);
const sidebarPanelWrapper = document.getElementById('tabbrowser-tabbox');
for (let id of kElementsToAppend) {
const elem = document.getElementById(id);
if (elem) {
sidebarPanelWrapper.prepend(elem);
}
}
}
#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);
Services.prefs.setStringPref('zen.updates.last-build-id', Services.appinfo.appBuildID);
Services.scriptloader.loadSubScript(
'chrome://browser/content/zen-components/ZenWelcome.mjs',
window
);
} else {
this.#createUpdateAnimation();
}
}
async #createUpdateAnimation() {
const appID = Services.appinfo.appBuildID;
if (
Services.prefs.getStringPref('zen.updates.last-build-id', '') === appID ||
gZenUIManager.testingEnabled
) {
return;
}
Services.prefs.setStringPref('zen.updates.last-build-id', appID);
await gZenWorkspaces.promiseInitialized;
const appWrapper = document.getElementById('zen-main-app-wrapper');
const element = document.createElement('div');
element.id = 'zen-update-animation';
const elementBorder = document.createElement('div');
elementBorder.id = 'zen-update-animation-border';
requestIdleCallback(() => {
if (gReduceMotion) {
return;
}
appWrapper.appendChild(element);
appWrapper.appendChild(elementBorder);
Promise.all([
gZenUIManager.motion.animate(
'#zen-update-animation',
{
top: ['100%', '-50%'],
opacity: [0.5, 1],
},
{
duration: 0.35,
}
),
gZenUIManager.motion.animate(
'#zen-update-animation-border',
{
'--background-top': ['150%', '-50%'],
},
{
duration: 0.35,
delay: 0.08,
}
),
]).then(() => {
element.remove();
elementBorder.remove();
});
});
}
})();
window.addEventListener(
'MozBeforeInitialXULLayout',
() => {
gZenStartup.init();
},
{ once: true }
);
}

View File

@@ -1,9 +1,11 @@
// 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/.
{
// prettier-ignore
const SVG_ICONS = [
import { nsZenDOMOperatedFeature } from 'chrome://browser/content/zen-components/ZenCommonUtils.mjs';
// prettier-ignore
const SVG_ICONS = [
"airplane.svg", "american-football.svg", "baseball.svg", "basket.svg",
"bed.svg", "bell.svg", "bookmark.svg", "book.svg",
"briefcase.svg", "brush.svg", "bug.svg", "build.svg",
@@ -28,204 +30,201 @@
"water.svg", "weight.svg",
];
class nsZenEmojiPicker extends nsZenDOMOperatedFeature {
#panel;
class nsZenEmojiPicker extends nsZenDOMOperatedFeature {
#panel;
#anchor;
#anchor;
#currentPromise = null;
#currentPromiseResolve = null;
#currentPromiseReject = null;
#currentPromise = null;
#currentPromiseResolve = null;
#currentPromiseReject = null;
init() {
this.#panel = document.getElementById('PanelUI-zen-emojis-picker');
this.#panel.addEventListener('popupshowing', this);
this.#panel.addEventListener('popuphidden', this);
this.#panel.addEventListener('command', this);
this.searchInput.addEventListener('input', this);
}
init() {
this.#panel = document.getElementById('PanelUI-zen-emojis-picker');
this.#panel.addEventListener('popupshowing', this);
this.#panel.addEventListener('popuphidden', this);
this.#panel.addEventListener('command', this);
this.searchInput.addEventListener('input', this);
}
handleEvent(event) {
switch (event.type) {
case 'popupshowing':
this.#onPopupShowing(event);
break;
case 'popuphidden':
this.#onPopupHidden(event);
break;
case 'command':
if (event.target.id === 'PanelUI-zen-emojis-picker-none') {
this.#selectEmoji(null);
} else if (event.target.id === 'PanelUI-zen-emojis-picker-change-emojis') {
this.#changePage(false);
} else if (event.target.id === 'PanelUI-zen-emojis-picker-change-svg') {
this.#changePage(true);
}
break;
case 'input':
this.#onSearchInput(event);
break;
}
}
get #emojis() {
if (this._emojis) {
return this._emojis;
}
const lazy = {};
Services.scriptloader.loadSubScript(
'chrome://browser/content/zen-components/ZenEmojisData.min.mjs',
lazy
);
this._emojis = lazy.ZenEmojisData;
return this._emojis;
}
get emojiList() {
return document.getElementById('PanelUI-zen-emojis-picker-list');
}
get svgList() {
return document.getElementById('PanelUI-zen-emojis-picker-svgs');
}
get searchInput() {
return document.getElementById('PanelUI-zen-emojis-picker-search');
}
#changePage(toSvg = false) {
const itemToScroll = toSvg
? this.svgList
: document
.getElementById('PanelUI-zen-emojis-picker-pages')
.querySelector('[emojis="true"]');
itemToScroll.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
inline: 'start',
});
const button = document.getElementById(
`PanelUI-zen-emojis-picker-change-${toSvg ? 'svg' : 'emojis'}`
);
const otherButton = document.getElementById(
`PanelUI-zen-emojis-picker-change-${toSvg ? 'emojis' : 'svg'}`
);
button.classList.add('selected');
otherButton.classList.remove('selected');
}
#clearEmojis() {
delete this._emojis;
}
#onSearchInput(event) {
const input = event.target;
const value = input.value.trim().toLowerCase();
// search for emojis.tags and order by emojis.order
const filteredEmojis = this.#emojis
.filter((emoji) => {
return emoji.tags.some((tag) => tag.toLowerCase().includes(value));
})
.sort((a, b) => a.order - b.order);
for (const button of this.emojiList.children) {
const buttonEmoji = button.getAttribute('label');
const emojiObject = filteredEmojis.find((emoji) => emoji.emoji === buttonEmoji);
if (emojiObject) {
button.hidden = !emojiObject.tags.some((tag) => tag.toLowerCase().includes(value));
button.style.order = emojiObject.order;
} else {
button.hidden = true;
handleEvent(event) {
switch (event.type) {
case 'popupshowing':
this.#onPopupShowing(event);
break;
case 'popuphidden':
this.#onPopupHidden(event);
break;
case 'command':
if (event.target.id === 'PanelUI-zen-emojis-picker-none') {
this.#selectEmoji(null);
} else if (event.target.id === 'PanelUI-zen-emojis-picker-change-emojis') {
this.#changePage(false);
} else if (event.target.id === 'PanelUI-zen-emojis-picker-change-svg') {
this.#changePage(true);
}
}
}
// note: It's async on purpose so we can render the popup before processing the emojis
async #onPopupShowing(event) {
if (event.target !== this.#panel) return;
this.searchInput.value = '';
const allowEmojis = !this.#panel.hasAttribute('only-svg-icons');
if (allowEmojis) {
const emojiList = this.emojiList;
for (const emoji of this.#emojis) {
const item = document.createXULElement('toolbarbutton');
item.className = 'toolbarbutton-1 zen-emojis-picker-emoji';
item.setAttribute('label', emoji.emoji);
item.setAttribute('tooltiptext', '');
item.addEventListener('command', () => {
this.#selectEmoji(emoji.emoji);
});
emojiList.appendChild(item);
}
setTimeout(() => {
this.searchInput.focus();
}, 500);
}
const svgList = this.svgList;
for (const icon of SVG_ICONS) {
const item = document.createXULElement('toolbarbutton');
item.className = 'toolbarbutton-1 zen-emojis-picker-svg';
item.setAttribute('label', icon);
item.setAttribute('tooltiptext', '');
item.style.listStyleImage = `url(${this.getSVGURL(icon)})`;
item.setAttribute('icon', icon);
item.addEventListener('command', () => {
this.#selectEmoji(this.getSVGURL(icon));
});
svgList.appendChild(item);
}
}
#onPopupHidden(event) {
if (event.target !== this.#panel) return;
this.#clearEmojis();
this.#changePage(false);
const emojiList = this.emojiList;
emojiList.innerHTML = '';
this.svgList.innerHTML = '';
if (this.#currentPromiseReject) {
this.#currentPromiseReject(new Error('Emoji picker closed without selection'));
}
this.#currentPromise = null;
this.#currentPromiseResolve = null;
this.#currentPromiseReject = null;
this.#anchor.removeAttribute('zen-emoji-open');
this.#anchor = null;
}
#selectEmoji(emoji) {
this.#currentPromiseResolve?.(emoji);
this.#panel.hidePopup();
}
open(anchor, { onlySvgIcons = false } = {}) {
if (this.#currentPromise) {
return null;
}
this.#currentPromise = new Promise((resolve, reject) => {
this.#currentPromiseResolve = resolve;
this.#currentPromiseReject = reject;
});
this.#anchor = anchor;
this.#anchor.setAttribute('zen-emoji-open', 'true');
if (onlySvgIcons) {
this.#panel.setAttribute('only-svg-icons', 'true');
} else {
this.#panel.removeAttribute('only-svg-icons');
}
this.#panel.openPopup(anchor, 'after_start', 0, 0, false, false);
return this.#currentPromise;
}
getSVGURL(icon) {
return `chrome://browser/skin/zen-icons/selectable/${icon}`;
break;
case 'input':
this.#onSearchInput(event);
break;
}
}
window.gZenEmojiPicker = new nsZenEmojiPicker();
get #emojis() {
if (this._emojis) {
return this._emojis;
}
const lazy = {};
Services.scriptloader.loadSubScript(
'chrome://browser/content/zen-components/ZenEmojisData.min.mjs',
lazy
);
this._emojis = lazy.ZenEmojisData;
return this._emojis;
}
get emojiList() {
return document.getElementById('PanelUI-zen-emojis-picker-list');
}
get svgList() {
return document.getElementById('PanelUI-zen-emojis-picker-svgs');
}
get searchInput() {
return document.getElementById('PanelUI-zen-emojis-picker-search');
}
#changePage(toSvg = false) {
const itemToScroll = toSvg
? this.svgList
: document.getElementById('PanelUI-zen-emojis-picker-pages').querySelector('[emojis="true"]');
itemToScroll.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
inline: 'start',
});
const button = document.getElementById(
`PanelUI-zen-emojis-picker-change-${toSvg ? 'svg' : 'emojis'}`
);
const otherButton = document.getElementById(
`PanelUI-zen-emojis-picker-change-${toSvg ? 'emojis' : 'svg'}`
);
button.classList.add('selected');
otherButton.classList.remove('selected');
}
#clearEmojis() {
delete this._emojis;
}
#onSearchInput(event) {
const input = event.target;
const value = input.value.trim().toLowerCase();
// search for emojis.tags and order by emojis.order
const filteredEmojis = this.#emojis
.filter((emoji) => {
return emoji.tags.some((tag) => tag.toLowerCase().includes(value));
})
.sort((a, b) => a.order - b.order);
for (const button of this.emojiList.children) {
const buttonEmoji = button.getAttribute('label');
const emojiObject = filteredEmojis.find((emoji) => emoji.emoji === buttonEmoji);
if (emojiObject) {
button.hidden = !emojiObject.tags.some((tag) => tag.toLowerCase().includes(value));
button.style.order = emojiObject.order;
} else {
button.hidden = true;
}
}
}
// note: It's async on purpose so we can render the popup before processing the emojis
async #onPopupShowing(event) {
if (event.target !== this.#panel) return;
this.searchInput.value = '';
const allowEmojis = !this.#panel.hasAttribute('only-svg-icons');
if (allowEmojis) {
const emojiList = this.emojiList;
for (const emoji of this.#emojis) {
const item = document.createXULElement('toolbarbutton');
item.className = 'toolbarbutton-1 zen-emojis-picker-emoji';
item.setAttribute('label', emoji.emoji);
item.setAttribute('tooltiptext', '');
item.addEventListener('command', () => {
this.#selectEmoji(emoji.emoji);
});
emojiList.appendChild(item);
}
setTimeout(() => {
this.searchInput.focus();
}, 500);
}
const svgList = this.svgList;
for (const icon of SVG_ICONS) {
const item = document.createXULElement('toolbarbutton');
item.className = 'toolbarbutton-1 zen-emojis-picker-svg';
item.setAttribute('label', icon);
item.setAttribute('tooltiptext', '');
item.style.listStyleImage = `url(${this.getSVGURL(icon)})`;
item.setAttribute('icon', icon);
item.addEventListener('command', () => {
this.#selectEmoji(this.getSVGURL(icon));
});
svgList.appendChild(item);
}
}
#onPopupHidden(event) {
if (event.target !== this.#panel) return;
this.#clearEmojis();
this.#changePage(false);
const emojiList = this.emojiList;
emojiList.innerHTML = '';
this.svgList.innerHTML = '';
if (this.#currentPromiseReject) {
this.#currentPromiseReject(new Error('Emoji picker closed without selection'));
}
this.#currentPromise = null;
this.#currentPromiseResolve = null;
this.#currentPromiseReject = null;
this.#anchor.removeAttribute('zen-emoji-open');
this.#anchor = null;
}
#selectEmoji(emoji) {
this.#currentPromiseResolve?.(emoji);
this.#panel.hidePopup();
}
open(anchor, { onlySvgIcons = false } = {}) {
if (this.#currentPromise) {
return null;
}
this.#currentPromise = new Promise((resolve, reject) => {
this.#currentPromiseResolve = resolve;
this.#currentPromiseReject = reject;
});
this.#anchor = anchor;
this.#anchor.setAttribute('zen-emoji-open', 'true');
if (onlySvgIcons) {
this.#panel.setAttribute('only-svg-icons', 'true');
} else {
this.#panel.removeAttribute('only-svg-icons');
}
this.#panel.openPopup(anchor, 'after_start', 0, 0, false, false);
return this.#currentPromise;
}
getSVGURL(icon) {
return `chrome://browser/skin/zen-icons/selectable/${icon}`;
}
}
window.gZenEmojiPicker = new nsZenEmojiPicker();

View File

@@ -1,4 +1,3 @@
#
# 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/.

36
src/zen/common/jar.inc.mn Normal file
View File

@@ -0,0 +1,36 @@
# 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/.
content/browser/zenThemeModifier.js (../../zen/common/zenThemeModifier.js)
content/browser/ZenPreloadedScripts.js (../../zen/common/ZenPreloadedScripts.js)
content/browser/zen-sets.js (../../zen/common/zen-sets.js)
content/browser/ZenStartup.mjs (../../zen/common/modules/ZenStartup.mjs)
content/browser/ZenUpdates.mjs (../../zen/common/modules/ZenUpdates.mjs)
content/browser/ZenUIManager.mjs (../../zen/common/modules/ZenUIManager.mjs)
content/browser/zen-components/ZenCommonUtils.mjs (../../zen/common/modules/ZenCommonUtils.mjs)
content/browser/zen-components/ZenSessionStore.mjs (../../zen/common/modules/ZenSessionStore.mjs)
content/browser/zen-components/ZenHasPolyfill.mjs (../../zen/common/modules/ZenHasPolyfill.mjs)
content/browser/zen-components/ZenSidebarNotification.mjs (../../zen/common/modules/ZenSidebarNotification.mjs)
content/browser/zen-components/ZenEmojisData.min.mjs (../../zen/common/emojis/ZenEmojisData.min.mjs)
content/browser/zen-components/ZenEmojiPicker.mjs (../../zen/common/emojis/ZenEmojiPicker.mjs)
* content/browser/zen-styles/zen-theme.css (../../zen/common/styles/zen-theme.css)
content/browser/zen-styles/zen-buttons.css (../../zen/common/styles/zen-buttons.css)
content/browser/zen-styles/zen-browser-ui.css (../../zen/common/styles/zen-browser-ui.css)
content/browser/zen-styles/zen-animations.css (../../zen/common/styles/zen-animations.css)
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-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)
content/browser/zen-styles/zen-branding.css (../../zen/common/styles/zen-branding.css)
content/browser/zen-styles/zen-sidebar-notification.css (../../zen/common/styles/zen-sidebar-notification.css)
content/browser/zen-styles/zen-panels/bookmarks.css (../../zen/common/styles/zen-panels/bookmarks.css)
content/browser/zen-styles/zen-panels/print.css (../../zen/common/styles/zen-panels/print.css)
content/browser/zen-styles/zen-panels/dialog.css (../../zen/common/styles/zen-panels/dialog.css)

View File

@@ -15,8 +15,7 @@ window.gZenOperatingSystemCommonUtils = {
},
};
/* eslint-disable no-unused-vars */
class nsZenMultiWindowFeature {
export class nsZenMultiWindowFeature {
constructor() {}
static get browsers() {
@@ -50,23 +49,21 @@ class nsZenMultiWindowFeature {
}
}
/* eslint-disable no-unused-vars */
class nsZenDOMOperatedFeature {
export class nsZenDOMOperatedFeature {
constructor() {
var initBound = this.init.bind(this);
document.addEventListener('DOMContentLoaded', initBound, { once: true });
}
}
/* eslint-disable no-unused-vars */
class nsZenPreloadedFeature {
export class nsZenPreloadedFeature {
constructor() {
var initBound = this.init.bind(this);
document.addEventListener('MozBeforeInitialXULLayout', initBound, { once: true });
}
}
var gZenCommonActions = {
window.gZenCommonActions = {
copyCurrentURLToClipboard() {
const [currentUrl, ClipboardHelper] = gURLBar.zenStrippedURI;
const displaySpec = currentUrl.displaySpec;

View File

@@ -0,0 +1,75 @@
// 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/.
class nsHasPolyfill {
constructor() {
this.observers = [];
this.idStore = 0;
}
/**
* @param {{selector: string, exists: boolean}} descendantSelectors
*/
observeSelectorExistence(element, descendantSelectors, stateAttribute, attributeFilter = []) {
const updateState = () => {
const exists = descendantSelectors.some(({ selector }) => {
let selected = element.querySelector(selector);
if (selected?.tagName?.toLowerCase() === 'menu') {
return null;
}
return selected;
});
const { exists: shouldExist = true } = descendantSelectors;
if (exists === shouldExist) {
if (!element.hasAttribute(stateAttribute)) {
gZenCompactModeManager._setElementExpandAttribute(element, true, stateAttribute);
}
} else {
if (element.hasAttribute(stateAttribute)) {
gZenCompactModeManager._setElementExpandAttribute(element, false, stateAttribute);
}
}
};
const observer = new MutationObserver(updateState);
updateState();
const observerId = this.idStore++;
this.observers.push({
id: observerId,
observer,
element,
attributeFilter,
});
return observerId;
}
disconnectObserver(observerId) {
const index = this.observers.findIndex((o) => o.id === observerId);
if (index !== -1) {
this.observers[index].observer.disconnect();
}
}
connectObserver(observerId) {
const observer = this.observers.find((o) => o.id === observerId);
if (observer) {
observer.observer.observe(observer.element, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: observer.attributeFilter.length ? observer.attributeFilter : undefined,
});
}
}
destroy() {
this.observers.forEach((observer) => observer.observer.disconnect());
this.observers = [];
}
}
const hasPolyfillInstance = new nsHasPolyfill();
window.addEventListener('unload', () => hasPolyfillInstance.destroy(), { once: true });
window.ZenHasPolyfill = hasPolyfillInstance;

View File

@@ -0,0 +1,47 @@
// 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 { nsZenPreloadedFeature } from 'chrome://browser/content/zen-components/ZenCommonUtils.mjs';
class ZenSessionStore extends nsZenPreloadedFeature {
init() {
this.#waitAndCleanup();
}
promiseInitialized = new Promise((resolve) => {
this._resolveInitialized = resolve;
});
restoreInitialTabData(tab, tabData) {
if (tabData.zenWorkspace) {
tab.setAttribute('zen-workspace-id', tabData.zenWorkspace);
}
if (tabData.zenPinnedId) {
tab.setAttribute('zen-pin-id', tabData.zenPinnedId);
}
if (tabData.zenHasStaticLabel) {
tab.setAttribute('zen-has-static-label', 'true');
}
if (tabData.zenEssential) {
tab.setAttribute('zen-essential', 'true');
}
if (tabData.zenDefaultUserContextId) {
tab.setAttribute('zenDefaultUserContextId', 'true');
}
if (tabData.zenPinnedEntry) {
tab.setAttribute('zen-pinned-entry', tabData.zenPinnedEntry);
}
}
async #waitAndCleanup() {
await SessionStore.promiseInitialized;
this.#cleanup();
}
#cleanup() {
this._resolveInitialized();
}
}
window.gZenSessionStore = new ZenSessionStore();

View File

@@ -0,0 +1,128 @@
/* 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 { html } from 'chrome://global/content/vendor/lit.all.mjs';
import { MozLitElement } from 'chrome://global/content/lit-utils.mjs';
const lazy = {};
ChromeUtils.defineLazyGetter(lazy, 'siblingElement', () => {
// All our notifications should be attached after the media controls toolbar
return document.getElementById('zen-media-controls-toolbar');
});
/**
* Zen Sidebar Notification Component
*
* Displays and takes care of animations for notifications that
* appear in the sidebar.
*
* @properties {headingL10nId} - The L10n ID for the heading text.
*/
class ZenSidebarNotification extends MozLitElement {
static properties = {
headingL10nId: { type: String, fluent: true },
links: { type: Array },
};
constructor({ headingL10nId = '', links = [] } = {}) {
super();
this.headingL10nId = headingL10nId;
this.links = links;
}
connectedCallback() {
super.connectedCallback();
if (this.parentElement) {
this.#animateIn();
}
}
remove() {
this.#animateOut().then(() => {
super.remove();
});
}
render() {
return html`
<link
rel="stylesheet"
href="chrome://browser/content/zen-styles/zen-sidebar-notification.css" />
<div class="zen-sidebar-notification-header">
<label
class="zen-sidebar-notification-heading"
flex="1"
data-l10n-id="${this.headingL10nId}"></label>
<div class="zen-sidebar-notification-close-button" @click=${() => this.remove()}>
<img src="chrome://browser/skin/zen-icons/close.svg" />
</div>
</div>
<div class="zen-sidebar-notification-body">
${this.links.map(
(link) => html`
<div
class="zen-sidebar-notification-link-container"
data-l10n-id="${link.l10nId}-tooltip"
?special=${link.special}
@click=${() => {
if (link.action) {
link.action();
return;
}
window.openLinkIn(link.url, 'tab', {
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
forceForeground: true,
});
this.remove();
}}>
<img class="zen-sidebar-notification-link-icon" src="${link.icon}" />
<label
class="zen-sidebar-notification-link-text"
data-l10n-id="${link.l10nId}-label"></label>
</div>
`
)}
</div>
`;
}
#animateIn() {
this.style.opacity = '0';
return gZenUIManager.motion.animate(
this,
{
opacity: [0, 1],
y: [50, 0],
},
{
delay: 1,
}
);
}
#animateOut() {
return gZenUIManager.motion.animate(
this,
{
opacity: [1, 0],
y: [0, 10],
},
{}
);
}
}
export default function createSidebarNotification(args) {
if (!gZenVerticalTabsManager._prefsSidebarExpanded) {
return null;
}
const notification = new ZenSidebarNotification(args);
lazy.siblingElement.insertAdjacentElement('afterend', notification);
return notification;
}
customElements.define('zen-sidebar-notification', ZenSidebarNotification);

View File

@@ -0,0 +1,188 @@
// 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 checkForZenUpdates, {
createWindowUpdateAnimation,
} from 'chrome://browser/content/ZenUpdates.mjs';
class ZenStartup {
#watermarkIgnoreElements = ['zen-toast-container'];
#hasInitializedLayout = false;
isReady = false;
async init() {
// important: We do this to ensure that some firefox components
// are initialized before we start our own initialization.
// please, do not remove this line and if you do, make sure to
// test the startup process.
await new Promise((resolve) => setTimeout(resolve, 0));
this.openWatermark();
this.#initBrowserBackground();
this.#changeSidebarLocation();
this.#zenInitBrowserLayout();
}
#initBrowserBackground() {
const background = document.createXULElement('box');
background.id = 'zen-browser-background';
background.classList.add('zen-browser-generic-background');
const grain = document.createXULElement('box');
grain.classList.add('zen-browser-grain');
background.appendChild(grain);
document.getElementById('browser').prepend(background);
const toolbarBackground = background.cloneNode(true);
toolbarBackground.removeAttribute('id');
toolbarBackground.classList.add('zen-toolbar-background');
document.getElementById('titlebar').prepend(toolbarBackground);
}
#zenInitBrowserLayout() {
if (this.#hasInitializedLayout) return;
this.#hasInitializedLayout = true;
try {
const kNavbarItems = ['nav-bar', 'PersonalToolbar'];
const kNewContainerId = 'zen-appcontent-navbar-container';
let newContainer = document.getElementById(kNewContainerId);
for (let id of kNavbarItems) {
const node = document.getElementById(id);
console.assert(node, 'Could not find node with id: ' + id);
if (!node) continue;
newContainer.appendChild(node);
}
// Fix notification deck
const deckTemplate = document.getElementById('tab-notification-deck-template');
if (deckTemplate) {
document.getElementById('zen-appcontent-wrapper').prepend(deckTemplate);
}
gZenWorkspaces.init();
setTimeout(() => {
gZenUIManager.init();
this.#checkForWelcomePage();
}, 0);
} catch (e) {
console.error('ZenThemeModifier: Error initializing browser layout', e);
}
if (gBrowserInit.delayedStartupFinished) {
this.delayedStartupFinished();
} else {
Services.obs.addObserver(this, 'browser-delayed-startup-finished');
}
}
observe(aSubject, aTopic) {
// This nsIObserver method allows us to defer initialization until after
// this window has finished painting and starting up.
if (aTopic == 'browser-delayed-startup-finished' && aSubject == window) {
Services.obs.removeObserver(this, 'browser-delayed-startup-finished');
this.delayedStartupFinished();
}
}
delayedStartupFinished() {
gZenWorkspaces.promiseInitialized.then(async () => {
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')) {
gURLBar.focus();
}
// A bit of a hack to make sure the tabs toolbar is updated.
// Just in case we didn't get the right size.
gZenUIManager.updateTabsToolbar();
this.closeWatermark();
checkForZenUpdates();
this.isReady = true;
});
}
openWatermark() {
if (!Services.prefs.getBoolPref('zen.watermark.enabled', false)) {
document.documentElement.removeAttribute('zen-before-loaded');
return;
}
for (let elem of document.querySelectorAll('#browser > *, #urlbar')) {
elem.style.opacity = 0;
}
}
closeWatermark() {
document.documentElement.removeAttribute('zen-before-loaded');
if (Services.prefs.getBoolPref('zen.watermark.enabled', false)) {
let elementsToIgnore = this.#watermarkIgnoreElements.map((id) => '#' + id).join(', ');
gZenUIManager.motion
.animate(
'#browser > *:not(' + elementsToIgnore + '), #urlbar, #tabbrowser-tabbox > *',
{
opacity: [0, 1],
},
{
duration: 0.1,
}
)
.then(() => {
for (let elem of document.querySelectorAll(
'#browser > *, #urlbar, #tabbrowser-tabbox > *'
)) {
elem.style.removeProperty('opacity');
}
});
}
window.requestAnimationFrame(() => {
window.dispatchEvent(new window.Event('resize')); // To recalculate the layout
});
}
#changeSidebarLocation() {
const kElementsToAppend = ['sidebar-splitter', 'sidebar-box'];
const browser = document.getElementById('browser');
browser.prepend(gNavToolbox);
const sidebarPanelWrapper = document.getElementById('tabbrowser-tabbox');
for (let id of kElementsToAppend) {
const elem = document.getElementById(id);
if (elem) {
sidebarPanelWrapper.prepend(elem);
}
}
}
#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);
Services.prefs.setStringPref('zen.updates.last-build-id', Services.appinfo.appBuildID);
Services.scriptloader.loadSubScript(
'chrome://browser/content/zen-components/ZenWelcome.mjs',
window
);
} else {
this.#createUpdateAnimation();
}
}
async #createUpdateAnimation() {
return await createWindowUpdateAnimation();
}
}
window.gZenStartup = new ZenStartup();
window.addEventListener(
'MozBeforeInitialXULLayout',
() => {
gZenStartup.init();
},
{ once: true }
);

View File

@@ -2,7 +2,9 @@
// 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/.
var gZenUIManager = {
import { nsZenMultiWindowFeature } from 'chrome://browser/content/zen-components/ZenCommonUtils.mjs';
window.gZenUIManager = {
_popupTrackingElements: [],
_hoverPausedForExpand: false,
_hasLoadedDOM: false,
@@ -444,29 +446,29 @@ var gZenUIManager = {
gURLBar._zenHandleUrlbarClose = null;
}
const isFocusedBefore = gURLBar.focused;
setTimeout(() => {
// We use this attribute on Tabbrowser::addTab
gURLBar.removeAttribute('zen-newtab');
}, 0);
// Safely restore tab visual state with proper validation
if (
this._lastTab &&
!this._lastTab.closing &&
this._lastTab.ownerGlobal &&
!this._lastTab.ownerGlobal.closed
) {
this._lastTab._visuallySelected = true;
this._lastTab = null;
}
// Safely restore tab visual state with proper validation
if (
this._lastTab &&
!this._lastTab.closing &&
this._lastTab.ownerGlobal &&
!this._lastTab.ownerGlobal.closed &&
!onSwitch
) {
this._lastTab._visuallySelected = true;
this._lastTab = null;
}
// Reset newtab buttons
for (const button of this.newtabButtons) {
button.removeAttribute('in-urlbar');
}
// Reset newtab buttons
for (const button of this.newtabButtons) {
button.removeAttribute('in-urlbar');
}
// Handle search data
if (!onElementPicked) {
// Handle search data
if (onSwitch) {
this.clearUrlbarData();
} else {
@@ -487,28 +489,30 @@ var gZenUIManager = {
}
gURLBar.handleRevert();
} else if (onElementPicked && onSwitch) {
this.clearUrlbarData();
}
if (gURLBar.focused) {
setTimeout(() => {
window.dispatchEvent(
new CustomEvent('ZenURLBarClosed', { detail: { onSwitch, onElementPicked } })
);
gURLBar.view.close({ elementPicked: onElementPicked });
gURLBar.updateTextOverflow();
if (isFocusedBefore) {
setTimeout(() => {
window.dispatchEvent(
new CustomEvent('ZenURLBarClosed', { detail: { onSwitch, onElementPicked } })
);
gURLBar.view.close({ elementPicked: onElementPicked });
gURLBar.updateTextOverflow();
// Ensure tab and browser are valid before updating state
const selectedTab = gBrowser.selectedTab;
if (selectedTab && selectedTab.linkedBrowser && !selectedTab.closing && onSwitch) {
const browserState = gURLBar.getBrowserState(selectedTab.linkedBrowser);
if (browserState) {
browserState.urlbarFocused = false;
if (onElementPicked && onSwitch) {
gURLBar.setURI(null, onSwitch);
}
}
}, 0);
}
// Ensure tab and browser are valid before updating state
const selectedTab = gBrowser.selectedTab;
if (selectedTab && selectedTab.linkedBrowser && !selectedTab.closing && onSwitch) {
const browserState = gURLBar.getBrowserState(selectedTab.linkedBrowser);
if (browserState) {
browserState.urlbarFocused = false;
}
}
}, 0);
}
}, 0);
},
urlbarTrim(aURL) {
@@ -663,7 +667,10 @@ var gZenUIManager = {
if (anchor?.closest('#zen-sidebar-top-buttons')) {
block = 'topleft';
}
if (gZenVerticalTabsManager._hasSetSingleToolbar && gZenVerticalTabsManager._prefsRightSide) {
if (
(gZenVerticalTabsManager._hasSetSingleToolbar && gZenVerticalTabsManager._prefsRightSide) ||
(panel?.id === 'zen-unified-site-data-panel' && !gZenVerticalTabsManager._hasSetSingleToolbar)
) {
block = 'bottomright';
inline = 'topright';
}
@@ -715,7 +722,7 @@ XPCOMUtils.defineLazyPreferenceGetter(
true
);
var gZenVerticalTabsManager = {
window.gZenVerticalTabsManager = {
init() {
this._multiWindowFeature = new nsZenMultiWindowFeature();
this._initWaitPromise();

View File

@@ -0,0 +1,89 @@
// 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 createSidebarNotification from 'chrome://browser/content/zen-components/ZenSidebarNotification.mjs';
const ZEN_UPDATE_PREF = 'zen.updates.last-version';
const ZEN_BUILD_ID_PREF = 'zen.updates.last-build-id';
const ZEN_UPDATE_SHOW = 'zen.updates.show-update-notification';
export default function checkForZenUpdates() {
const version = Services.appinfo.version;
const lastVersion = Services.prefs.getStringPref(ZEN_UPDATE_PREF, version);
if (
version !== lastVersion &&
!gZenUIManager.testingEnabled &&
Services.prefs.getBoolPref(ZEN_UPDATE_SHOW, true)
) {
const updateUrl = Services.prefs.getStringPref('app.releaseNotesURL.prompt', '');
createSidebarNotification({
headingL10nId: 'zen-sidebar-notification-updated-heading',
links: [
{
url: Services.urlFormatter.formatURL(updateUrl.replace('%VERSION%', version)),
l10nId: 'zen-sidebar-notification-updated',
special: true,
icon: 'chrome://browser/skin/zen-icons/heart-circle-fill.svg',
},
{
action: () => {
Services.obs.notifyObservers(window, 'restart-in-safe-mode');
},
l10nId: 'zen-sidebar-notification-restart-safe-mode',
icon: 'chrome://browser/skin/zen-icons/security-broken.svg',
},
],
});
}
}
export async function createWindowUpdateAnimation() {
const appID = Services.appinfo.appBuildID;
if (
Services.prefs.getStringPref(ZEN_BUILD_ID_PREF, '') === appID ||
gZenUIManager.testingEnabled
) {
return;
}
Services.prefs.setStringPref(ZEN_BUILD_ID_PREF, appID);
await gZenWorkspaces.promiseInitialized;
const appWrapper = document.getElementById('zen-main-app-wrapper');
const element = document.createElement('div');
element.id = 'zen-update-animation';
const elementBorder = document.createElement('div');
elementBorder.id = 'zen-update-animation-border';
requestIdleCallback(() => {
if (gReduceMotion) {
return;
}
appWrapper.appendChild(element);
appWrapper.appendChild(elementBorder);
Promise.all([
gZenUIManager.motion.animate(
'#zen-update-animation',
{
top: ['100%', '-50%'],
opacity: [0.5, 1],
},
{
duration: 0.35,
}
),
gZenUIManager.motion.animate(
'#zen-update-animation-border',
{
'--background-top': ['150%', '-50%'],
},
{
duration: 0.35,
delay: 0.08,
}
),
]).then(() => {
element.remove();
elementBorder.remove();
});
});
}

View File

@@ -3,7 +3,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXTRA_JS_MODULES += [
"ZenActorsManager.sys.mjs",
"ZenCustomizableUI.sys.mjs",
"ZenUIMigration.sys.mjs",
"sys/ZenActorsManager.sys.mjs",
"sys/ZenCustomizableUI.sys.mjs",
"sys/ZenUIMigration.sys.mjs",
]

View File

@@ -355,6 +355,8 @@
}
:root:not([zen-single-toolbar='true']) {
--urlbar-icon-border-radius: 6px !important;
#notification-popup-box {
margin: 0 4px 0 0 !important;
justify-content: center;

View File

@@ -0,0 +1,122 @@
/*
* 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/.
*/
@keyframes zen-text-gradient {
0% {
background-position: 0% 50%;
}
100% {
background-position: 100% 50%;
}
}
:host {
background: var(--zen-sidebar-notification-bg);
display: flex;
flex-direction: column;
min-width: 0;
border-radius: var(--border-radius-medium);
box-shadow: var(--zen-sidebar-notification-shadow);
font-size: var(--font-size-medium);
}
.zen-sidebar-notification-header {
display: flex;
position: relative;
flex: 1;
padding: 8px;
border-bottom: 1px solid color-mix(in srgb, currentColor 10%, transparent);
}
.zen-sidebar-notification-heading {
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-weight: 500;
flex: 1;
}
.zen-sidebar-notification-close-button {
position: absolute;
right: 2px;
top: 2px;
border-radius: 4px;
border-top-right-radius: calc(var(--border-radius-medium) - 2px);
z-index: 1;
padding: 4px;
width: 18px;
height: 18px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
opacity: 0.4;
&:hover {
background: color-mix(in srgb, currentColor 15%, transparent);
}
& img {
-moz-context-properties: fill, fill-opacity;
fill-opacity: 1;
fill: currentColor;
width: 14px;
pointer-events: none;
}
}
.zen-sidebar-notification-body {
padding: 6px;
display: flex;
flex-direction: column;
gap: 2px;
& .zen-sidebar-notification-link-container {
cursor: pointer;
padding: 4px;
display: flex;
gap: 6px;
align-items: center;
transition: opacity 0.2s ease-in-out;
opacity: 0.7;
& .zen-sidebar-notification-link-text {
cursor: inherit;
}
&[special] {
opacity: 1;
--special-color: color-mix(in srgb, var(--zen-primary-color), currentColor 50%);
--specia-color-2: color-mix(in srgb, var(--zen-primary-color), currentColor 90%);
background: linear-gradient(
135deg,
var(--specia-color-2),
var(--special-color),
var(--specia-color-2),
var(--special-color)
);
background-size: 400%;
filter: saturate(3);
background-clip: text;
/* Still works on firefox */
-webkit-text-fill-color: transparent;
animation: zen-text-gradient 2s linear infinite;
}
&:hover {
opacity: 1;
}
& .zen-sidebar-notification-link-icon {
pointer-events: none;
width: 16px;
height: 16px;
-moz-context-properties: fill, fill-opacity;
fill: var(--special-color, currentColor);
}
}
}

View File

@@ -242,6 +242,14 @@
/* Define tab hover background color */
--tab-hover-background-color: var(--toolbarbutton-hover-background);
/* Sidebar Notifications */
--zen-sidebar-notification-bg: color-mix(
in srgb,
var(--zen-primary-color) 15%,
light-dark(white, black)
);
--zen-sidebar-notification-shadow: 0 0 6px light-dark(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.3));
/* Nativity */
--zen-native-content-radius: var(--zen-border-radius);
@media (-moz-platform: linux) {

View File

@@ -42,7 +42,7 @@ let JSWINDOWACTORS = {
esModuleURI: 'resource:///actors/ZenGlanceChild.sys.mjs',
events: {
DOMContentLoaded: {},
click: {
mousedown: {
capture: true,
},
keydown: {

View File

@@ -4,7 +4,7 @@
import { AppConstants } from 'resource://gre/modules/AppConstants.sys.mjs';
export var ZenCustomizableUI = new (class {
export const ZenCustomizableUI = new (class {
constructor() {}
TYPE_TOOLBAR = 'toolbar';

View File

@@ -95,7 +95,7 @@ var ZenThemeModifier = {
const kMinElementSeparation = 0.1; // in px
let separation = this.elementSeparation;
if (
window.fullScreen &&
document.documentElement.hasAttribute('inFullscreen') &&
window.gZenCompactModeManager?.preference &&
!document.getElementById('tabbrowser-tabbox')?.hasAttribute('zen-split-view') &&
Services.prefs.getBoolPref('zen.view.borderless-fullscreen', true)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
# 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/.
* content/browser/zen-styles/zen-compact-mode.css (../../zen/compact-mode/zen-compact-mode.css)
content/browser/zen-components/ZenCompactMode.mjs (../../zen/compact-mode/ZenCompactMode.mjs)

View File

@@ -106,7 +106,7 @@
right: calc(-1 * var(--actual-zen-sidebar-width) + var(--zen-element-separation) / 2 + 1px);
}
& .browserSidebarContainer {
& .browserSidebarContainer:not([is-zen-split='true']) {
margin-left: 0 !important;
margin-right: 0 !important;
}

View File

@@ -1,165 +1,169 @@
// 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/.
{
const { Downloads } = ChromeUtils.importESModule('resource://gre/modules/Downloads.sys.mjs');
const CONFIG = Object.freeze({
ANIMATION: {
ARC_STEPS: 60,
MAX_ARC_HEIGHT: 1200,
ARC_HEIGHT_RATIO: 0.8, // Arc height = distance * ratio (capped at MAX_ARC_HEIGHT)
SCALE_END: 0.45, // Final scale at destination
},
});
import { Downloads } from 'resource://gre/modules/Downloads.sys.mjs';
import {
nsZenDOMOperatedFeature,
nsZenMultiWindowFeature,
} from 'chrome://browser/content/zen-components/ZenCommonUtils.mjs';
class nsZenDownloadAnimation extends nsZenDOMOperatedFeature {
async init() {
await this.#setupDownloadListeners();
}
const CONFIG = Object.freeze({
ANIMATION: {
ARC_STEPS: 60,
MAX_ARC_HEIGHT: 1200,
ARC_HEIGHT_RATIO: 0.8, // Arc height = distance * ratio (capped at MAX_ARC_HEIGHT)
SCALE_END: 0.45, // Final scale at destination
},
});
async #setupDownloadListeners() {
try {
const list = await Downloads.getList(Downloads.ALL);
list.addView({
onDownloadAdded: this.#handleNewDownload.bind(this),
});
} catch (error) {
console.error(
`[${nsZenDownloadAnimation.name}] Failed to set up download animation listeners: ${error}`
);
}
}
class nsZenDownloadAnimation extends nsZenDOMOperatedFeature {
async init() {
await this.#setupDownloadListeners();
}
#handleNewDownload() {
if (
!Services.prefs.getBoolPref('zen.downloads.download-animation') ||
!nsZenMultiWindowFeature.isActiveWindow
) {
return;
}
if (!gZenUIManager._lastClickPosition) {
console.warn(
`[${nsZenDownloadAnimation.name}] No recent click position available for animation`
);
return;
}
this.#animateDownload(gZenUIManager._lastClickPosition);
}
#animateDownload(startPosition) {
let animationElement = document.querySelector('zen-download-animation');
if (!animationElement) {
animationElement = document.createElement('zen-download-animation');
document.body.appendChild(animationElement);
}
animationElement.initializeAnimation(startPosition);
async #setupDownloadListeners() {
try {
const list = await Downloads.getList(Downloads.ALL);
list.addView({
onDownloadAdded: this.#handleNewDownload.bind(this),
});
} catch (error) {
console.error(
`[${nsZenDownloadAnimation.name}] Failed to set up download animation listeners: ${error}`
);
}
}
class nsZenDownloadAnimationElement extends HTMLElement {
#boxAnimationElement = null;
#boxAnimationTimeoutId = null;
#isBoxAnimationRunning = false;
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.#loadArcStyles();
#handleNewDownload() {
if (
!Services.prefs.getBoolPref('zen.downloads.download-animation') ||
!nsZenMultiWindowFeature.isActiveWindow
) {
return;
}
#loadArcStyles() {
try {
const link = document.createElement('link');
link.setAttribute('rel', 'stylesheet');
link.setAttribute(
'href',
'chrome://browser/content/zen-styles/zen-download-arc-animation.css'
);
this.shadowRoot.appendChild(link);
} catch (error) {
console.error(`[${nsZenDownloadAnimationElement.name}] Error loading arc styles: ${error}`);
}
if (!gZenUIManager._lastClickPosition) {
console.warn(
`[${nsZenDownloadAnimation.name}] No recent click position available for animation`
);
return;
}
async initializeAnimation(startPosition) {
if (!startPosition) {
console.warn(
`[${nsZenDownloadAnimationElement.name}] No start position provided, skipping animation`
);
return;
}
this.#animateDownload(gZenUIManager._lastClickPosition);
}
// Determine animation target position
const { endPosition, isDownloadButtonVisible } = this.#determineEndPosition();
#animateDownload(startPosition) {
let animationElement = document.querySelector('zen-download-animation');
if (!animationElement) {
animationElement = document.createElement('zen-download-animation');
document.body.appendChild(animationElement);
}
animationElement.initializeAnimation(startPosition);
}
}
class nsZenDownloadAnimationElement extends HTMLElement {
#boxAnimationElement = null;
#boxAnimationTimeoutId = null;
#isBoxAnimationRunning = false;
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.#loadArcStyles();
}
#loadArcStyles() {
try {
const link = document.createElement('link');
link.setAttribute('rel', 'stylesheet');
link.setAttribute(
'href',
'chrome://browser/content/zen-styles/zen-download-arc-animation.css'
);
this.shadowRoot.appendChild(link);
} catch (error) {
console.error(`[${nsZenDownloadAnimationElement.name}] Error loading arc styles: ${error}`);
}
}
async initializeAnimation(startPosition) {
if (!startPosition) {
console.warn(
`[${nsZenDownloadAnimationElement.name}] No start position provided, skipping animation`
);
return;
}
// Determine animation target position
const { endPosition, isDownloadButtonVisible } = this.#determineEndPosition();
const areTabsPositionedRight = this.#areTabsOnRightSide();
// Create and prepare the arc animation element
const arcAnimationElement = this.#createArcAnimationElement(startPosition);
// Calculate optimal arc parameters based on available space
const distance = this.#calculateDistance(startPosition, endPosition);
const { arcHeight, shouldArcDownward } = this.#calculateOptimalArc(
startPosition,
endPosition,
distance
);
const distanceX = endPosition.clientX - startPosition.clientX;
const distanceY = endPosition.clientY - startPosition.clientY;
const arcSequence = this.#createArcAnimationSequence(
distanceX,
distanceY,
arcHeight,
shouldArcDownward
);
// Start the download animation
await this.#startDownloadAnimation(
areTabsPositionedRight,
isDownloadButtonVisible,
arcAnimationElement,
arcSequence
);
}
#areTabsOnRightSide() {
return Services.prefs.getBoolPref('zen.tabs.vertical.right-side');
}
#determineEndPosition() {
const downloadsButton = document.getElementById('downloads-button');
const isDownloadButtonVisible = downloadsButton && this.#isElementVisible(downloadsButton);
let endPosition = { clientX: 0, clientY: 0 };
if (isDownloadButtonVisible) {
// Use download button as target
const buttonRect = downloadsButton.getBoundingClientRect();
endPosition = {
clientX: buttonRect.left + buttonRect.width / 2,
clientY: buttonRect.top + buttonRect.height / 2,
};
} else {
// Use alternative position at bottom of wrapper
const areTabsPositionedRight = this.#areTabsOnRightSide();
const wrapper = document.getElementById('zen-main-app-wrapper');
const wrapperRect = wrapper.getBoundingClientRect();
// Create and prepare the arc animation element
const arcAnimationElement = this.#createArcAnimationElement(startPosition);
// Calculate optimal arc parameters based on available space
const distance = this.#calculateDistance(startPosition, endPosition);
const { arcHeight, shouldArcDownward } = this.#calculateOptimalArc(
startPosition,
endPosition,
distance
);
const distanceX = endPosition.clientX - startPosition.clientX;
const distanceY = endPosition.clientY - startPosition.clientY;
const arcSequence = this.#createArcAnimationSequence(
distanceX,
distanceY,
arcHeight,
shouldArcDownward
);
// Start the download animation
await this.#startDownloadAnimation(
areTabsPositionedRight,
isDownloadButtonVisible,
arcAnimationElement,
arcSequence
);
endPosition = {
clientX: areTabsPositionedRight ? wrapperRect.right - 42 : wrapperRect.left + 42,
clientY: wrapperRect.bottom - 40,
};
}
#areTabsOnRightSide() {
return Services.prefs.getBoolPref('zen.tabs.vertical.right-side');
}
return { endPosition, isDownloadButtonVisible };
}
#determineEndPosition() {
const downloadsButton = document.getElementById('downloads-button');
const isDownloadButtonVisible = downloadsButton && this.#isElementVisible(downloadsButton);
let endPosition = { clientX: 0, clientY: 0 };
if (isDownloadButtonVisible) {
// Use download button as target
const buttonRect = downloadsButton.getBoundingClientRect();
endPosition = {
clientX: buttonRect.left + buttonRect.width / 2,
clientY: buttonRect.top + buttonRect.height / 2,
};
} else {
// Use alternative position at bottom of wrapper
const areTabsPositionedRight = this.#areTabsOnRightSide();
const wrapper = document.getElementById('zen-main-app-wrapper');
const wrapperRect = wrapper.getBoundingClientRect();
endPosition = {
clientX: areTabsPositionedRight ? wrapperRect.right - 42 : wrapperRect.left + 42,
clientY: wrapperRect.bottom - 40,
};
}
return { endPosition, isDownloadButtonVisible };
}
#createArcAnimationElement(startPosition) {
const arcAnimationHTML = `
#createArcAnimationElement(startPosition) {
const arcAnimationHTML = `
<box class="zen-download-arc-animation">
<box class="zen-download-arc-animation-inner-circle">
<html:div class="zen-download-arc-animation-icon"></html:div>
@@ -167,328 +171,327 @@
</box>
`;
const fragment = window.MozXULElement.parseXULToFragment(arcAnimationHTML);
const animationElement = fragment.querySelector('.zen-download-arc-animation');
const fragment = window.MozXULElement.parseXULToFragment(arcAnimationHTML);
const animationElement = fragment.querySelector('.zen-download-arc-animation');
Object.assign(animationElement.style, {
left: `${startPosition.clientX}px`,
top: `${startPosition.clientY}px`,
transform: 'translate(-50%, -50%)',
Object.assign(animationElement.style, {
left: `${startPosition.clientX}px`,
top: `${startPosition.clientY}px`,
transform: 'translate(-50%, -50%)',
});
this.shadowRoot.appendChild(animationElement);
return animationElement;
}
#calculateOptimalArc(startPosition, endPosition, distance) {
// Calculate available space for the arc
const availableTopSpace = Math.min(startPosition.clientY, endPosition.clientY);
const viewportHeight = window.innerHeight;
const availableBottomSpace =
viewportHeight - Math.max(startPosition.clientY, endPosition.clientY);
// Determine if we should arc downward or upward based on available space
const shouldArcDownward = availableBottomSpace > availableTopSpace;
// Use the space in the direction we're arcing
const availableSpace = shouldArcDownward ? availableBottomSpace : availableTopSpace;
// Limit arc height to a percentage of the available space
const arcHeight = Math.min(
distance * CONFIG.ANIMATION.ARC_HEIGHT_RATIO,
CONFIG.ANIMATION.MAX_ARC_HEIGHT,
availableSpace * 0.8
);
return { arcHeight, shouldArcDownward };
}
#calculateDistance(start, end) {
const distanceX = end.clientX - start.clientX;
const distanceY = end.clientY - start.clientY;
return Math.sqrt(distanceX * distanceX + distanceY * distanceY);
}
async #startDownloadAnimation(
areTabsPositionedRight,
isDownloadButtonVisible,
arcAnimationElement,
sequence
) {
try {
if (!isDownloadButtonVisible) {
this.#startBoxAnimation(areTabsPositionedRight);
}
await gZenUIManager.motion.animate(arcAnimationElement, sequence, {
duration: Services.prefs.getIntPref('zen.downloads.download-animation-duration') / 1000,
easing: 'cubic-bezier(0.37, 0, 0.63, 1)',
fill: 'forwards',
});
this.shadowRoot.appendChild(animationElement);
this.#cleanArcAnimation(arcAnimationElement);
} catch (error) {
console.error('[nsZenDownloadAnimationElement] Error in animation sequence:', error);
this.#cleanArcAnimation(arcAnimationElement);
}
}
return animationElement;
#createArcAnimationSequence(distanceX, distanceY, arcHeight, shouldArcDownward) {
const sequence = { offset: [], opacity: [], transform: [] };
const arcDirection = shouldArcDownward ? 1 : -1;
const steps = CONFIG.ANIMATION.ARC_STEPS;
const endScale = CONFIG.ANIMATION.SCALE_END;
function easeInOutQuad(t) {
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
}
#calculateOptimalArc(startPosition, endPosition, distance) {
// Calculate available space for the arc
const availableTopSpace = Math.min(startPosition.clientY, endPosition.clientY);
const viewportHeight = window.innerHeight;
const availableBottomSpace =
viewportHeight - Math.max(startPosition.clientY, endPosition.clientY);
let previousRotation = 0;
for (let i = 0; i <= steps; i++) {
const progress = i / steps;
const eased = easeInOutQuad(progress);
// Determine if we should arc downward or upward based on available space
const shouldArcDownward = availableBottomSpace > availableTopSpace;
// Calculate opacity changes
let opacity;
if (progress < 0.3) {
// Fade in during first 30%
opacity = 0.3 + (progress / 0.3) * 0.6;
} else if (progress < 0.98) {
// Slight increase to full opacity
opacity = 0.9 + ((progress - 0.3) / 0.6) * 0.1;
} else {
// Decrease opacity in the final steps
opacity = 1 - ((progress - 0.9) / 0.1) * 1;
}
// Use the space in the direction we're arcing
const availableSpace = shouldArcDownward ? availableBottomSpace : availableTopSpace;
// Calculate scaling changes
let scale;
if (progress < 0.5) {
scale = 0.5 + (progress / 0.5) * 1.3;
} else {
scale = 1.8 - ((progress - 0.5) / 0.5) * (1.8 - endScale);
}
// Limit arc height to a percentage of the available space
const arcHeight = Math.min(
distance * CONFIG.ANIMATION.ARC_HEIGHT_RATIO,
CONFIG.ANIMATION.MAX_ARC_HEIGHT,
availableSpace * 0.8
// Position on arc
const x = distanceX * eased;
const y = distanceY * eased + arcDirection * arcHeight * (1 - (2 * eased - 1) ** 2);
// Calculate rotation to point in the direction of movement
let rotation = previousRotation;
if (i > 0) {
const prevEased = easeInOutQuad((i - 1) / steps);
const prevX = distanceX * prevEased;
const prevAdjustedProgress = prevEased * 2 - 1;
const prevVerticalOffset = arcDirection * arcHeight * (1 - prevAdjustedProgress * 2);
const prevY = distanceY * prevEased + prevVerticalOffset;
const targetRotation = Math.atan2(y - prevY, x - prevX) * (180 / Math.PI);
rotation += (targetRotation - previousRotation) * 0.01;
previousRotation = rotation;
}
sequence.offset.push(progress);
sequence.opacity.push(opacity);
sequence.transform.push(
`translate(calc(${x}px - 50%), calc(${y}px - 50%)) rotate(${rotation}deg) scale(${scale})`
);
return { arcHeight, shouldArcDownward };
}
#calculateDistance(start, end) {
const distanceX = end.clientX - start.clientX;
const distanceY = end.clientY - start.clientY;
return Math.sqrt(distanceX * distanceX + distanceY * distanceY);
return sequence;
}
#cleanArcAnimation(element) {
element.remove();
}
async #startBoxAnimation(areTabsPositionedRight) {
// If animation is already in progress, don't start a new one
if (this.#isBoxAnimationRunning) {
console.warn(
`[${nsZenDownloadAnimationElement.name}] Box animation already running, skipping new request.`
);
return;
}
async #startDownloadAnimation(
areTabsPositionedRight,
isDownloadButtonVisible,
arcAnimationElement,
sequence
) {
try {
if (!isDownloadButtonVisible) {
this.#startBoxAnimation(areTabsPositionedRight);
}
await gZenUIManager.motion.animate(arcAnimationElement, sequence, {
duration: Services.prefs.getIntPref('zen.downloads.download-animation-duration') / 1000,
easing: 'cubic-bezier(0.37, 0, 0.63, 1)',
fill: 'forwards',
});
this.#cleanArcAnimation(arcAnimationElement);
} catch (error) {
console.error('[nsZenDownloadAnimationElement] Error in animation sequence:', error);
this.#cleanArcAnimation(arcAnimationElement);
}
if (this.#boxAnimationElement) {
clearTimeout(this.#boxAnimationTimeoutId);
this.#boxAnimationTimeoutId = setTimeout(
() => this.#finishBoxAnimation(areTabsPositionedRight),
this.#getBoxAnimationDurationMs()
);
return;
}
#createArcAnimationSequence(distanceX, distanceY, arcHeight, shouldArcDownward) {
const sequence = { offset: [], opacity: [], transform: [] };
const arcDirection = shouldArcDownward ? 1 : -1;
const steps = CONFIG.ANIMATION.ARC_STEPS;
const endScale = CONFIG.ANIMATION.SCALE_END;
function easeInOutQuad(t) {
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
}
let previousRotation = 0;
for (let i = 0; i <= steps; i++) {
const progress = i / steps;
const eased = easeInOutQuad(progress);
// Calculate opacity changes
let opacity;
if (progress < 0.3) {
// Fade in during first 30%
opacity = 0.3 + (progress / 0.3) * 0.6;
} else if (progress < 0.98) {
// Slight increase to full opacity
opacity = 0.9 + ((progress - 0.3) / 0.6) * 0.1;
} else {
// Decrease opacity in the final steps
opacity = 1 - ((progress - 0.9) / 0.1) * 1;
}
// Calculate scaling changes
let scale;
if (progress < 0.5) {
scale = 0.5 + (progress / 0.5) * 1.3;
} else {
scale = 1.8 - ((progress - 0.5) / 0.5) * (1.8 - endScale);
}
// Position on arc
const x = distanceX * eased;
const y = distanceY * eased + arcDirection * arcHeight * (1 - (2 * eased - 1) ** 2);
// Calculate rotation to point in the direction of movement
let rotation = previousRotation;
if (i > 0) {
const prevEased = easeInOutQuad((i - 1) / steps);
const prevX = distanceX * prevEased;
const prevAdjustedProgress = prevEased * 2 - 1;
const prevVerticalOffset = arcDirection * arcHeight * (1 - prevAdjustedProgress * 2);
const prevY = distanceY * prevEased + prevVerticalOffset;
const targetRotation = Math.atan2(y - prevY, x - prevX) * (180 / Math.PI);
rotation += (targetRotation - previousRotation) * 0.01;
previousRotation = rotation;
}
sequence.offset.push(progress);
sequence.opacity.push(opacity);
sequence.transform.push(
`translate(calc(${x}px - 50%), calc(${y}px - 50%)) rotate(${rotation}deg) scale(${scale})`
);
}
return sequence;
const wrapper = document.getElementById('zen-main-app-wrapper');
if (!wrapper) {
console.warn(
`[${nsZenDownloadAnimationElement.name}] Cannot start box animation, Wrapper element not found`
);
return;
}
#cleanArcAnimation(element) {
element.remove();
}
this.#isBoxAnimationRunning = true;
async #startBoxAnimation(areTabsPositionedRight) {
// If animation is already in progress, don't start a new one
if (this.#isBoxAnimationRunning) {
console.warn(
`[${nsZenDownloadAnimationElement.name}] Box animation already running, skipping new request.`
);
return;
}
if (this.#boxAnimationElement) {
clearTimeout(this.#boxAnimationTimeoutId);
this.#boxAnimationTimeoutId = setTimeout(
() => this.#finishBoxAnimation(areTabsPositionedRight),
this.#getBoxAnimationDurationMs()
);
return;
}
const wrapper = document.getElementById('zen-main-app-wrapper');
if (!wrapper) {
console.warn(
`[${nsZenDownloadAnimationElement.name}] Cannot start box animation, Wrapper element not found`
);
return;
}
this.#isBoxAnimationRunning = true;
try {
const boxAnimationHTML = `
try {
const boxAnimationHTML = `
<box class="zen-download-box-animation">
<html:div class="zen-download-box-animation-icon"></html:div>
</box>
`;
const sideProp = areTabsPositionedRight ? 'right' : 'left';
const sideProp = areTabsPositionedRight ? 'right' : 'left';
const fragment = window.MozXULElement.parseXULToFragment(boxAnimationHTML);
this.#boxAnimationElement = fragment.querySelector('.zen-download-box-animation');
const fragment = window.MozXULElement.parseXULToFragment(boxAnimationHTML);
this.#boxAnimationElement = fragment.querySelector('.zen-download-box-animation');
Object.assign(this.#boxAnimationElement.style, {
bottom: '24px',
transform: 'scale(0.8)',
[sideProp]: '-50px',
});
Object.assign(this.#boxAnimationElement.style, {
bottom: '24px',
transform: 'scale(0.8)',
[sideProp]: '-50px',
});
wrapper.appendChild(this.#boxAnimationElement);
wrapper.appendChild(this.#boxAnimationElement);
await gZenUIManager.motion.animate(
this.#boxAnimationElement,
{
[sideProp]: '34px',
opacity: 1,
transform: 'scale(1.1)',
},
{
duration: 0.35,
easing: 'ease-out',
}
).finished;
await gZenUIManager.motion.animate(
this.#boxAnimationElement,
{
[sideProp]: '24px',
transform: 'scale(1)',
},
{
duration: 0.2,
easing: 'ease-in-out',
}
).finished;
clearTimeout(this.#boxAnimationTimeoutId);
this.#boxAnimationTimeoutId = setTimeout(
() => this.#finishBoxAnimation(areTabsPositionedRight),
this.#getBoxAnimationDurationMs()
);
} catch (error) {
console.error(
`[${nsZenDownloadAnimationElement.name}] Error during box entry animation: ${error}`
);
this.#cleanBoxAnimation();
} finally {
this.#isBoxAnimationRunning = false;
}
}
#getBoxAnimationDurationMs() {
return Services.prefs.getIntPref('zen.downloads.download-animation-duration') + 200;
}
async #finishBoxAnimation(areTabsPositionedRight) {
clearTimeout(this.#boxAnimationTimeoutId);
this.#boxAnimationTimeoutId = null;
if (!this.#boxAnimationElement || this.#isBoxAnimationRunning) {
if (!this.#boxAnimationElement) this.#cleanBoxAnimationState();
return;
}
this.#isBoxAnimationRunning = true;
try {
const sideProp = areTabsPositionedRight ? 'right' : 'left';
await gZenUIManager.motion.animate(
this.#boxAnimationElement,
{
transform: 'scale(0.9)',
},
{
duration: 0.15,
easing: 'ease-in',
}
).finished;
await gZenUIManager.motion.animate(
this.#boxAnimationElement,
{
[sideProp]: '-50px',
opacity: 0,
transform: 'scale(0.8)',
},
{
duration: 0.3,
easing: 'cubic-bezier(0.5, 0, 0.75, 0)',
}
).finished;
} catch (error) {
console.warn(
`[${nsZenDownloadAnimationElement.name}] Error during box exit animation: ${error}`
);
} finally {
this.#cleanBoxAnimation();
}
}
#cleanBoxAnimationState() {
this.#boxAnimationElement = null;
if (this.#boxAnimationTimeoutId) {
clearTimeout(this.#boxAnimationTimeoutId);
this.#boxAnimationTimeoutId = null;
}
this.#isBoxAnimationRunning = false;
}
#cleanBoxAnimation() {
if (this.#boxAnimationElement && this.#boxAnimationElement.isConnected) {
try {
this.#boxAnimationElement.remove();
} catch (error) {
console.error(
`[${nsZenDownloadAnimationElement.name}] Error removing box animation element: ${error}`,
error
);
await gZenUIManager.motion.animate(
this.#boxAnimationElement,
{
[sideProp]: '34px',
opacity: 1,
transform: 'scale(1.1)',
},
{
duration: 0.35,
easing: 'ease-out',
}
}
this.#cleanBoxAnimationState();
}
).finished;
#isElementVisible(element) {
if (!element) return false;
await gZenUIManager.motion.animate(
this.#boxAnimationElement,
{
[sideProp]: '24px',
transform: 'scale(1)',
},
{
duration: 0.2,
easing: 'ease-in-out',
}
).finished;
const rect = element.getBoundingClientRect();
// Element must be in the viewport
// Is 1 and no 0 because if you pin the download button in the overflow menu
// the download button is in the viewport but in the position 0,0 so this
// avoid this case
if (
rect.bottom < 1 ||
rect.right < 1 ||
rect.top > window.innerHeight ||
rect.left > window.innerWidth
) {
return false;
}
return true;
clearTimeout(this.#boxAnimationTimeoutId);
this.#boxAnimationTimeoutId = setTimeout(
() => this.#finishBoxAnimation(areTabsPositionedRight),
this.#getBoxAnimationDurationMs()
);
} catch (error) {
console.error(
`[${nsZenDownloadAnimationElement.name}] Error during box entry animation: ${error}`
);
this.#cleanBoxAnimation();
} finally {
this.#isBoxAnimationRunning = false;
}
}
customElements.define('zen-download-animation', nsZenDownloadAnimationElement);
#getBoxAnimationDurationMs() {
return Services.prefs.getIntPref('zen.downloads.download-animation-duration') + 200;
}
new nsZenDownloadAnimation();
async #finishBoxAnimation(areTabsPositionedRight) {
clearTimeout(this.#boxAnimationTimeoutId);
this.#boxAnimationTimeoutId = null;
if (!this.#boxAnimationElement || this.#isBoxAnimationRunning) {
if (!this.#boxAnimationElement) this.#cleanBoxAnimationState();
return;
}
this.#isBoxAnimationRunning = true;
try {
const sideProp = areTabsPositionedRight ? 'right' : 'left';
await gZenUIManager.motion.animate(
this.#boxAnimationElement,
{
transform: 'scale(0.9)',
},
{
duration: 0.15,
easing: 'ease-in',
}
).finished;
await gZenUIManager.motion.animate(
this.#boxAnimationElement,
{
[sideProp]: '-50px',
opacity: 0,
transform: 'scale(0.8)',
},
{
duration: 0.3,
easing: 'cubic-bezier(0.5, 0, 0.75, 0)',
}
).finished;
} catch (error) {
console.warn(
`[${nsZenDownloadAnimationElement.name}] Error during box exit animation: ${error}`
);
} finally {
this.#cleanBoxAnimation();
}
}
#cleanBoxAnimationState() {
this.#boxAnimationElement = null;
if (this.#boxAnimationTimeoutId) {
clearTimeout(this.#boxAnimationTimeoutId);
this.#boxAnimationTimeoutId = null;
}
this.#isBoxAnimationRunning = false;
}
#cleanBoxAnimation() {
if (this.#boxAnimationElement && this.#boxAnimationElement.isConnected) {
try {
this.#boxAnimationElement.remove();
} catch (error) {
console.error(
`[${nsZenDownloadAnimationElement.name}] Error removing box animation element: ${error}`,
error
);
}
}
this.#cleanBoxAnimationState();
}
#isElementVisible(element) {
if (!element) return false;
const rect = element.getBoundingClientRect();
// Element must be in the viewport
// Is 1 and no 0 because if you pin the download button in the overflow menu
// the download button is in the viewport but in the position 0,0 so this
// avoid this case
if (
rect.bottom < 1 ||
rect.right < 1 ||
rect.top > window.innerHeight ||
rect.left > window.innerWidth
) {
return false;
}
return true;
}
}
customElements.define('zen-download-animation', nsZenDownloadAnimationElement);
new nsZenDownloadAnimation();

View 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/.
content/browser/zen-components/ZenDownloadAnimation.mjs (../../zen/downloads/ZenDownloadAnimation.mjs)
content/browser/zen-styles/zen-download-arc-animation.css (../../zen/downloads/zen-download-arc-animation.css)
content/browser/zen-styles/zen-download-box-animation.css (../../zen/downloads/zen-download-box-animation.css)

View File

@@ -1,11 +1,11 @@
// 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/.
{
class ZenFolder extends MozTabbrowserTabGroup {
#initialized = false;
static markup = `
class ZenFolder extends MozTabbrowserTabGroup {
#initialized = false;
static markup = `
<hbox class="tab-group-label-container" pack="center">
<html:div class="tab-group-folder-icon"/>
<label class="tab-group-label" role="button"/>
@@ -19,8 +19,8 @@
</vbox>
`;
static rawIcon = new DOMParser().parseFromString(
`
static rawIcon = new DOMParser().parseFromString(
`
<svg width="28" height="28" viewBox="0 0 28 28" 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">
@@ -53,230 +53,227 @@
<ellipse cx="18" cy="16" rx="1.25" ry="1.25"/>
</g>
</svg>`,
'image/svg+xml'
).documentElement;
'image/svg+xml'
).documentElement;
constructor() {
super();
constructor() {
super();
}
connectedCallback() {
super.connectedCallback();
this.labelElement.pinned = true;
if (this.#initialized) {
return;
}
this.#initialized = true;
this._activeTabs = [];
this.icon.appendChild(ZenFolder.rawIcon.cloneNode(true));
connectedCallback() {
super.connectedCallback();
this.labelElement.pinned = true;
if (this.#initialized) {
return;
}
this.#initialized = true;
this._activeTabs = [];
this.icon.appendChild(ZenFolder.rawIcon.cloneNode(true));
this.labelElement.parentElement.setAttribute('context', 'zenFolderActions');
this.labelElement.parentElement.setAttribute('context', 'zenFolderActions');
this.labelElement.onRenameFinished = (newLabel) => {
this.name = newLabel.trim() || 'Folder';
const event = new CustomEvent('ZenFolderRenamed', {
bubbles: true,
});
this.dispatchEvent(event);
};
if (this.collapsed) {
this.querySelector('.tab-group-container').setAttribute('hidden', true);
}
}
get icon() {
return this.querySelector('.tab-group-folder-icon');
}
/**
* Returns the group this folder belongs to.
* @returns {MozTabbrowserTabGroup|null} The group this folder belongs to, or null if it is not part of a group.
**/
get group() {
if (gBrowser.isTabGroup(this.parentElement?.parentElement)) {
return this.parentElement.parentElement;
}
return null;
}
get isZenFolder() {
return true;
}
get activeGroups() {
let activeGroups = [];
let currentGroup = this;
if (currentGroup?.hasAttribute('has-active')) activeGroups.push(currentGroup);
while (currentGroup?.group) {
currentGroup = currentGroup?.group;
if (currentGroup?.hasAttribute('has-active')) {
activeGroups.push(currentGroup);
}
}
return activeGroups;
}
get childActiveGroups() {
return Array.from(this.querySelectorAll('zen-folder[has-active]'));
}
rename() {
if (!document.documentElement.hasAttribute('zen-sidebar-expanded')) {
return;
}
gZenVerticalTabsManager.renameTabStart({
target: this.labelElement,
explicit: true,
this.labelElement.onRenameFinished = (newLabel) => {
this.name = newLabel.trim() || 'Folder';
const event = new CustomEvent('ZenFolderRenamed', {
bubbles: true,
});
}
this.dispatchEvent(event);
};
createSubfolder() {
// We need to expand all parent folders
let currentFolder = this;
do {
currentFolder.collapsed = false;
currentFolder = currentFolder.group;
} while (currentFolder);
gZenFolders.createFolder([], {
renameFolder: !gZenUIManager.testingEnabled,
label: 'Subfolder',
insertAfter: this.querySelector('.tab-group-container').lastElementChild,
});
}
async unpackTabs() {
this.collapsed = false;
for (let tab of this.allItems.reverse()) {
tab = tab.group.hasAttribute('split-view-group') ? tab.group : tab;
if (tab.hasAttribute('zen-empty-tab')) {
await ZenPinnedTabsStorage.removePin(tab.getAttribute('zen-pin-id'));
gBrowser.removeTab(tab);
} else {
gBrowser.ungroupTab(tab);
}
}
}
async delete() {
for (const tab of this.allItemsRecursive) {
await ZenPinnedTabsStorage.removePin(tab.getAttribute('zen-pin-id'));
if (tab.hasAttribute('zen-empty-tab')) {
// Manually remove the empty tabs as removeTabs() inside removeTabGroup
// does ignore them.
gBrowser.removeTab(tab);
}
}
await gBrowser.removeTabGroup(this, { isUserTriggered: true });
}
get allItemsRecursive() {
const items = [];
for (const item of this.allItems) {
if (item.isZenFolder) {
items.push(item, ...item.allItemsRecursive);
} else {
items.push(item);
}
}
return items;
}
get allItems() {
return [...this.querySelector('.tab-group-container').children].filter(
(child) => !child.classList.contains('zen-tab-group-start')
);
}
get pinned() {
return this.isZenFolder;
}
/**
* Intentionally ignore attempts to change the pinned state.
* ZenFolder instances determine their "pinned" status based on their type (isZenFolder)
* and do not support being pinned or unpinned via this setter.
* This no-op setter ensures compatibility with interfaces expecting a pinned property,
* while preserving the invariant that ZenFolders cannot have their pinned state changed externally.
*/
set pinned(value) {}
get iconURL() {
return this.icon.querySelector('image')?.getAttribute('href') || '';
}
set activeTabs(tabs) {
if (tabs.length) {
this._activeTabs = tabs;
for (let tab of tabs) {
tab.setAttribute('folder-active', 'true');
}
} else {
const folders = new Map();
for (let tab of this._activeTabs) {
const group = tab?.group?.hasAttribute('split-view-group')
? tab?.group?.group
: tab?.group;
if (!folders.has(group?.id)) {
folders.set(group?.id, group?.activeGroups?.at(-1));
}
let activeGroup = folders.get(group?.id);
if (!activeGroup) {
tab.removeAttribute('folder-active');
tab.style.removeProperty('--zen-folder-indent');
}
}
this._activeTabs = [];
folders.clear();
}
}
get activeTabs() {
return this._activeTabs;
}
get resetButton() {
return this.labelElement.parentElement.querySelector('.tab-reset-button');
}
unloadAllTabs(event) {
this.#unloadAllActiveTabs(event, /* noClose */ true);
}
async #unloadAllActiveTabs(event, noClose = false) {
await gZenPinnedTabManager.onCloseTabShortcut(event, this.tabs, {
noClose,
alwaysUnload: true,
folderToUnload: this,
});
this.activeTabs = [];
}
on_click(event) {
if (event.target === this.resetButton) {
event.stopPropagation();
this.unloadAllTabs(event);
return;
}
super.on_click(event);
}
/**
* Get the root most collapsed folder in the tree.
* @returns {ZenFolder|null} The root most collapsed folder, or null if none are collapsed.
*/
get rootMostCollapsedFolder() {
let current = this;
let rootMost = null;
do {
if (current.collapsed) {
rootMost = current;
}
current = current.group;
} while (current);
return rootMost;
if (this.collapsed) {
this.querySelector('.tab-group-container').setAttribute('hidden', true);
}
}
customElements.define('zen-folder', ZenFolder);
get icon() {
return this.querySelector('.tab-group-folder-icon');
}
/**
* Returns the group this folder belongs to.
* @returns {MozTabbrowserTabGroup|null} The group this folder belongs to, or null if it is not part of a group.
**/
get group() {
if (gBrowser.isTabGroup(this.parentElement?.parentElement)) {
return this.parentElement.parentElement;
}
return null;
}
get isZenFolder() {
return true;
}
get activeGroups() {
let activeGroups = [];
let currentGroup = this;
if (currentGroup?.hasAttribute('has-active')) activeGroups.push(currentGroup);
while (currentGroup?.group) {
currentGroup = currentGroup?.group;
if (currentGroup?.hasAttribute('has-active')) {
activeGroups.push(currentGroup);
}
}
return activeGroups;
}
get childActiveGroups() {
return Array.from(this.querySelectorAll('zen-folder[has-active]'));
}
rename() {
if (!document.documentElement.hasAttribute('zen-sidebar-expanded')) {
return;
}
gZenVerticalTabsManager.renameTabStart({
target: this.labelElement,
explicit: true,
});
}
createSubfolder() {
// We need to expand all parent folders
let currentFolder = this;
do {
currentFolder.collapsed = false;
currentFolder = currentFolder.group;
} while (currentFolder);
gZenFolders.createFolder([], {
renameFolder: !gZenUIManager.testingEnabled,
label: 'Subfolder',
insertAfter: this.querySelector('.tab-group-container').lastElementChild,
});
}
async unpackTabs() {
this.collapsed = false;
for (let tab of this.allItems.reverse()) {
tab = tab.group.hasAttribute('split-view-group') ? tab.group : tab;
if (tab.hasAttribute('zen-empty-tab')) {
await ZenPinnedTabsStorage.removePin(tab.getAttribute('zen-pin-id'));
gBrowser.removeTab(tab);
} else {
gBrowser.ungroupTab(tab);
}
}
}
async delete() {
for (const tab of this.allItemsRecursive) {
await ZenPinnedTabsStorage.removePin(tab.getAttribute('zen-pin-id'));
if (tab.hasAttribute('zen-empty-tab')) {
// Manually remove the empty tabs as removeTabs() inside removeTabGroup
// does ignore them.
gBrowser.removeTab(tab);
}
}
await gBrowser.removeTabGroup(this, { isUserTriggered: true });
}
get allItemsRecursive() {
const items = [];
for (const item of this.allItems) {
if (item.isZenFolder) {
items.push(item, ...item.allItemsRecursive);
} else {
items.push(item);
}
}
return items;
}
get allItems() {
return [...this.querySelector('.tab-group-container').children].filter(
(child) => !child.classList.contains('zen-tab-group-start')
);
}
get pinned() {
return this.isZenFolder;
}
/**
* Intentionally ignore attempts to change the pinned state.
* ZenFolder instances determine their "pinned" status based on their type (isZenFolder)
* and do not support being pinned or unpinned via this setter.
* This no-op setter ensures compatibility with interfaces expecting a pinned property,
* while preserving the invariant that ZenFolders cannot have their pinned state changed externally.
*/
set pinned(value) {}
get iconURL() {
return this.icon.querySelector('image')?.getAttribute('href') || '';
}
set activeTabs(tabs) {
if (tabs.length) {
this._activeTabs = tabs;
for (let tab of tabs) {
tab.setAttribute('folder-active', 'true');
}
} else {
const folders = new Map();
for (let tab of this._activeTabs) {
const group = tab?.group?.hasAttribute('split-view-group') ? tab?.group?.group : tab?.group;
if (!folders.has(group?.id)) {
folders.set(group?.id, group?.activeGroups?.at(-1));
}
let activeGroup = folders.get(group?.id);
if (!activeGroup) {
tab.removeAttribute('folder-active');
tab.style.removeProperty('--zen-folder-indent');
}
}
this._activeTabs = [];
folders.clear();
}
}
get activeTabs() {
return this._activeTabs;
}
get resetButton() {
return this.labelElement.parentElement.querySelector('.tab-reset-button');
}
unloadAllTabs(event) {
this.#unloadAllActiveTabs(event, /* noClose */ true);
}
async #unloadAllActiveTabs(event, noClose = false) {
await gZenPinnedTabManager.onCloseTabShortcut(event, this.tabs, {
noClose,
alwaysUnload: true,
folderToUnload: this,
});
this.activeTabs = [];
}
on_click(event) {
if (event.target === this.resetButton) {
event.stopPropagation();
this.unloadAllTabs(event);
return;
}
super.on_click(event);
}
/**
* Get the root most collapsed folder in the tree.
* @returns {ZenFolder|null} The root most collapsed folder, or null if none are collapsed.
*/
get rootMostCollapsedFolder() {
let current = this;
let rootMost = null;
do {
if (current.collapsed) {
rootMost = current;
}
current = current.group;
} while (current);
return rootMost;
}
}
customElements.define('zen-folder', ZenFolder);

File diff suppressed because it is too large Load Diff

View 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/.
content/browser/zen-components/ZenFolder.mjs (../../zen/folders/ZenFolder.mjs)
content/browser/zen-components/ZenFolders.mjs (../../zen/folders/ZenFolders.mjs)
content/browser/zen-styles/zen-folders.css (../../zen/folders/zen-folders.css)

6
src/zen/fonts/jar.inc.mn Normal file
View File

@@ -0,0 +1,6 @@
# 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/.
content/browser/zen-fonts/JunicodeVF-Italic.woff2 (../../zen/fonts/JunicodeVF-Italic.woff2)
content/browser/zen-fonts/JunicodeVF-Roman.woff2 (../../zen/fonts/JunicodeVF-Roman.woff2)

File diff suppressed because it is too large Load Diff

View File

@@ -35,9 +35,12 @@ export class ZenGlanceChild extends JSWindowActorChild {
}
#sendClickDataToParent(target, element) {
if (!element || !target) {
if (!element && !target) {
return;
}
if (!target) {
target = element;
}
// Get the largest element we can get. If the `A` element
// is a parent of the original target, use the anchor element,
// otherwise use the original target.
@@ -54,7 +57,7 @@ export class ZenGlanceChild extends JSWindowActorChild {
});
}
on_click(event) {
on_mousedown(event) {
// get closest A element
const target = event.target.closest('A');
const elementToRecord = event.originalTarget || event.target;

View File

@@ -0,0 +1,6 @@
# 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/.
content/browser/zen-components/ZenGlanceManager.mjs (../../zen/glance/ZenGlanceManager.mjs)
content/browser/zen-styles/zen-glance.css (../../zen/glance/zen-glance.css)

25
src/zen/images/jar.inc.mn Normal file
View File

@@ -0,0 +1,25 @@
# 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/.
content/browser/zen-images/brand-header.svg (../../zen/images/brand-header.svg)
content/browser/zen-images/layouts/collapsed.png (../../zen/images/layouts/collapsed.png)
content/browser/zen-images/layouts/multiple-toolbar.png (../../zen/images/layouts/multiple-toolbar.png)
content/browser/zen-images/layouts/single-toolbar.png (../../zen/images/layouts/single-toolbar.png)
content/browser/zen-images/grain-bg.png (../../zen/images/grain-bg.png)
content/browser/zen-images/note-indicator.svg (../../zen/images/note-indicator.svg)
content/browser/zen-images/downloads/download.svg (../../zen/images/downloads/download.svg)
content/browser/zen-images/downloads/archive.svg (../../zen/images/downloads/archive.svg)
# FavIcons for startup
content/browser/zen-images/favicons/calendar.svg (../../zen/images/favicons/calendar.svg)
content/browser/zen-images/favicons/discord.svg (../../zen/images/favicons/discord.svg)
content/browser/zen-images/favicons/figma.svg (../../zen/images/favicons/figma.svg)
content/browser/zen-images/favicons/github.svg (../../zen/images/favicons/github.svg)
content/browser/zen-images/favicons/notion.svg (../../zen/images/favicons/notion.svg)
content/browser/zen-images/favicons/obsidian.svg (../../zen/images/favicons/obsidian.svg)
content/browser/zen-images/favicons/slack.svg (../../zen/images/favicons/slack.svg)
content/browser/zen-images/favicons/reddit.svg (../../zen/images/favicons/reddit.svg)
content/browser/zen-images/favicons/x.svg (../../zen/images/favicons/x.svg)
content/browser/zen-images/favicons/trello.svg (../../zen/images/favicons/trello.svg)

View File

@@ -2,6 +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/.
import { nsZenMultiWindowFeature } from 'chrome://browser/content/zen-components/ZenCommonUtils.mjs';
const KEYCODE_MAP = {
F1: 'VK_F1',
F2: 'VK_F2',
@@ -123,7 +125,7 @@ const fixedL10nIds = {
const ZEN_MAIN_KEYSET_ID = 'mainKeyset';
const ZEN_DEVTOOLS_KEYSET_ID = 'devtoolsKeyset';
const ZEN_KEYSET_ID = 'zenKeyset';
window.ZEN_KEYSET_ID = 'zenKeyset';
const ZEN_COMPACT_MODE_SHORTCUTS_GROUP = 'zen-compact-mode';
const ZEN_WORKSPACE_SHORTCUTS_GROUP = 'zen-workspace';
@@ -1100,7 +1102,7 @@ class nsZenKeyboardShortcutsVersioner {
}
}
var gZenKeyboardShortcutsManager = {
window.gZenKeyboardShortcutsManager = {
loader: new nsZenKeyboardShortcutsLoader(),
_hasToLoadDevtools: false,
_inlineCommands: [],
@@ -1400,7 +1402,7 @@ document.addEventListener(
'MozBeforeInitialXULLayout',
() => {
if (Services.prefs.getBoolPref('zen.keyboard.shortcuts.enabled', false)) {
gZenKeyboardShortcutsManager.beforeInit();
window.gZenKeyboardShortcutsManager.beforeInit();
}
},
{ once: true }

5
src/zen/kbs/jar.inc.mn Normal file
View File

@@ -0,0 +1,5 @@
# 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/.
content/browser/zen-components/ZenKeyboardShortcuts.mjs (../../zen/kbs/ZenKeyboardShortcuts.mjs)

File diff suppressed because it is too large Load Diff

6
src/zen/media/jar.inc.mn Normal file
View File

@@ -0,0 +1,6 @@
# 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/.
content/browser/zen-components/ZenMediaController.mjs (../../zen/media/ZenMediaController.mjs)
content/browser/zen-styles/zen-media-controls.css (../../zen/media/zen-media-controls.css)

View File

@@ -9,8 +9,8 @@
--button-spacing: 2px;
display: flex;
justify-content: space-between;
min-width: 0;
justify-content: space-between;
background: transparent;
container-type: inline-size;
@@ -151,11 +151,6 @@
}
& > toolbaritem {
--zen-media-control-bg: color-mix(
in srgb,
var(--zen-primary-color) 15%,
light-dark(white, black)
);
flex-grow: 1;
padding: 0;
transition: padding 0.3s ease-out;
@@ -164,8 +159,8 @@
bottom: 0;
padding: 4px 6px;
border-radius: var(--border-radius-medium);
box-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
background-color: var(--zen-media-control-bg);
box-shadow: var(--zen-sidebar-notification-shadow);
background-color: var(--zen-sidebar-notification-bg);
width: 100%;
}
@@ -239,14 +234,14 @@
overflow-x: visible;
white-space: nowrap;
/* Overflow inner box shadow from the left to simulate overflow */
mask-image: linear-gradient(to left, transparent, var(--zen-media-control-bg) 0.6em);
mask-image: linear-gradient(to left, transparent, var(--zen-sidebar-notification-bg) 0.6em);
min-width: 1px;
&::before {
content: '';
position: absolute;
width: 0.6em;
background: linear-gradient(to right, var(--zen-media-control-bg) 0%, transparent 100%);
background: linear-gradient(to right, var(--zen-sidebar-notification-bg) 0%, transparent 100%);
pointer-events: none;
top: 6px;
left: 0;

File diff suppressed because it is too large Load Diff

5
src/zen/mods/jar.inc.mn Normal file
View File

@@ -0,0 +1,5 @@
# 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/.
content/browser/zen-components/ZenMods.mjs (../../zen/mods/ZenMods.mjs)

View File

@@ -2,6 +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/.
import { nsZenDOMOperatedFeature } from 'chrome://browser/content/zen-components/ZenCommonUtils.mjs';
class nsSplitLeafNode {
/**
* The percentage of the size of the parent the node takes up, dependent on parent direction this is either
@@ -1067,86 +1069,88 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
* @param {string|undefined} gridType - The type of grid layout.
*/
splitTabs(tabs, gridType, initialIndex = 0) {
// TODO: Add support for splitting essential tabs
tabs = tabs.filter((t) => !t.hidden && !t.hasAttribute('zen-empty-tab'));
if (tabs.length < 2 || tabs.length > this.MAX_TABS) {
return;
}
this.#withoutSplitViewTransition(() => {
// TODO: Add support for splitting essential tabs
tabs = tabs.filter((t) => !t.hidden && !t.hasAttribute('zen-empty-tab'));
if (tabs.length < 2 || tabs.length > this.MAX_TABS) {
return;
}
const existingSplitTab = tabs.find((tab) => tab.splitView);
if (existingSplitTab) {
this._moveTabsToContainer(tabs, tabs[initialIndex]);
const groupIndex = this._data.findIndex((group) => group.tabs.includes(existingSplitTab));
const group = this._data[groupIndex];
const gridTypeChange = gridType && group.gridType !== gridType;
const newTabsAdded = tabs.find((t) => !group.tabs.includes(t));
if (gridTypeChange || !newTabsAdded) {
// reset layout
group.gridType = gridType;
group.layoutTree = this.calculateLayoutTree(
[...new Set(group.tabs.concat(tabs))],
gridType
);
} else {
// Add any tabs that are not already in the group
const existingSplitTab = tabs.find((tab) => tab.splitView);
if (existingSplitTab) {
this._moveTabsToContainer(tabs, tabs[initialIndex]);
const groupIndex = this._data.findIndex((group) => group.tabs.includes(existingSplitTab));
const group = this._data[groupIndex];
const gridTypeChange = gridType && group.gridType !== gridType;
const newTabsAdded = tabs.find((t) => !group.tabs.includes(t));
if (gridTypeChange || !newTabsAdded) {
// reset layout
group.gridType = gridType;
group.layoutTree = this.calculateLayoutTree(
[...new Set(group.tabs.concat(tabs))],
gridType
);
} else {
// Add any tabs that are not already in the group
for (let i = 0; i < tabs.length; i++) {
const tab = tabs[i];
if (!group.tabs.includes(tab)) {
gBrowser.moveTabToGroup(tab, this._getSplitViewGroup(tabs));
group.tabs.push(tab);
this.addTabToSplit(tab, group.layoutTree);
}
}
}
if (this._sessionRestoring) {
return;
}
this.activateSplitView(group, true);
return;
}
// We are here if none of the tabs have been previously split
// If there's ANY pinned tab on the list, we clone the pinned tab
// state to all the tabs
const allArePinned = tabs.every((tab) => tab.pinned);
const thereIsOnePinned = tabs.some((tab) => tab.pinned);
const thereIsOneEssential = tabs.some((tab) => tab.hasAttribute('zen-essential'));
if (thereIsOneEssential || (thereIsOnePinned && !allArePinned)) {
for (let i = 0; i < tabs.length; i++) {
const tab = tabs[i];
if (!group.tabs.includes(tab)) {
gBrowser.moveTabToGroup(tab, this._getSplitViewGroup(tabs));
group.tabs.push(tab);
this.addTabToSplit(tab, group.layoutTree);
if (tab.pinned) {
tabs[i] = gBrowser.duplicateTab(tab, true);
}
}
}
gridType ??= 'grid';
const splitData = {
tabs,
gridType,
layoutTree: this.calculateLayoutTree(tabs, gridType),
};
this._data.push(splitData);
if (!this._sessionRestoring) {
window.gBrowser.selectedTab = tabs[initialIndex] ?? tabs[0];
}
// Add tabs to the split view group
let splitGroup = this._getSplitViewGroup(tabs);
if (splitGroup) {
for (const tab of tabs) {
if (!tab.group || tab.group !== splitGroup) {
gBrowser.moveTabToGroup(tab, splitGroup);
}
}
}
if (this._sessionRestoring) {
return;
}
this.activateSplitView(group, true);
return;
}
// We are here if none of the tabs have been previously split
// If there's ANY pinned tab on the list, we clone the pinned tab
// state to all the tabs
const allArePinned = tabs.every((tab) => tab.pinned);
const thereIsOnePinned = tabs.some((tab) => tab.pinned);
const thereIsOneEssential = tabs.some((tab) => tab.hasAttribute('zen-essential'));
if (thereIsOneEssential || (thereIsOnePinned && !allArePinned)) {
for (let i = 0; i < tabs.length; i++) {
const tab = tabs[i];
if (tab.pinned) {
tabs[i] = gBrowser.duplicateTab(tab, true);
}
}
}
gridType ??= 'grid';
const splitData = {
tabs,
gridType,
layoutTree: this.calculateLayoutTree(tabs, gridType),
};
this._data.push(splitData);
if (!this._sessionRestoring) {
window.gBrowser.selectedTab = tabs[initialIndex] ?? tabs[0];
}
// Add tabs to the split view group
let splitGroup = this._getSplitViewGroup(tabs);
if (splitGroup) {
for (const tab of tabs) {
if (!tab.group || tab.group !== splitGroup) {
gBrowser.moveTabToGroup(tab, splitGroup);
}
}
}
if (this._sessionRestoring) {
return;
}
this.activateSplitView(splitData);
this.activateSplitView(splitData);
});
}
addTabToSplit(tab, splitNode, prepend = true) {
@@ -1929,6 +1933,17 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
return true;
}
#withoutSplitViewTransition(callback) {
this.tabBrowserPanel.classList.add('zen-split-view-no-transition');
try {
callback();
} finally {
requestAnimationFrame(() => {
this.tabBrowserPanel.classList.remove('zen-split-view-no-transition');
}, 0);
}
}
createEmptySplit() {
const selectedTab = gBrowser.selectedTab;
const emptyTab = gZenWorkspaces._emptyTab;
@@ -1975,6 +1990,13 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
gZenUIManager.handleNewTab(false, false, 'tab', true);
}, 0);
}
get splitViewBrowsers() {
if (this.currentView < 0) {
return [];
}
return this._data[this.currentView].tabs.map((tab) => tab.linkedBrowser);
}
}
window.gZenViewSplitter = new nsZenViewSplitter();

View File

@@ -0,0 +1,6 @@
# 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/.
* content/browser/zen-styles/zen-decks.css (../../zen/split-view/zen-decks.css)
content/browser/zen-components/ZenViewSplitter.mjs (../../zen/split-view/ZenViewSplitter.mjs)

View File

@@ -58,7 +58,7 @@
margin-top: 0 !important;
}
#tabbrowser-tabpanels[zen-split-view='true']:not([zen-split-resizing]) > [zen-split='true'] {
#tabbrowser-tabpanels[zen-split-view='true']:not(.zen-split-view-no-transition):not([zen-split-resizing]) > [zen-split='true'] {
transition: inset 0.09s ease-out !important;
& browser {
transition: opacity 0.2s ease-out !important;

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,8 @@
// 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/.
var ZenPinnedTabsStorage = {
window.ZenPinnedTabsStorage = {
_saveCache: [],
async init() {

8
src/zen/tabs/jar.inc.mn Normal file
View File

@@ -0,0 +1,8 @@
# 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/.
content/browser/zen-components/ZenPinnedTabsStorage.mjs (../../zen/tabs/ZenPinnedTabsStorage.mjs)
content/browser/zen-components/ZenPinnedTabManager.mjs (../../zen/tabs/ZenPinnedTabManager.mjs)
* content/browser/zen-styles/zen-tabs.css (../../zen/tabs/zen-tabs.css)
content/browser/zen-styles/zen-tabs/vertical-tabs.css (../../zen/tabs/zen-tabs/vertical-tabs.css)

View File

@@ -649,7 +649,14 @@
}
}
&:is(:hover, [visuallyselected]) .tab-close-button {
&:not(:hover) {
.tab-close-button,
.tab-reset-button {
display: none;
}
}
&:is(:hover, [multiselected][selected]) .tab-close-button {
display: block;
--tab-inline-padding: 0;
margin-inline-end: 0;

View File

@@ -1,3 +1,6 @@
/* Any copyright is dedicated to the Public Domain.
https://creativecommons.org/publicdomain/zero/1.0/ */
'use strict';
const URL1 = 'data:text/plain,tab1';

Some files were not shown because too many files have changed in this diff Show More