mirror of
https://github.com/zen-browser/desktop.git
synced 2025-11-09 20:15:03 +00:00
Compare commits
17 Commits
1.17.6b
...
window-syn
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf1b0dcd48 | ||
|
|
76acc8b0e4 | ||
|
|
1b83b77cad | ||
|
|
79ff574978 | ||
|
|
af20a65fa1 | ||
|
|
4a7f8fc9c0 | ||
|
|
a738a829de | ||
|
|
240a031e38 | ||
|
|
9bc7b9ce4e | ||
|
|
86006c8891 | ||
|
|
a55b1c7495 | ||
|
|
6e6337a95b | ||
|
|
6b12153c8a | ||
|
|
f6922ef2ba | ||
|
|
91f5d58fbc | ||
|
|
7a4cdaa45c | ||
|
|
81e854a89f |
@@ -6,7 +6,7 @@ if test "$ZEN_CROSS_COMPILING"; then
|
|||||||
|
|
||||||
export WINSYSROOT="$(echo ~)/win-cross/vs2022"
|
export WINSYSROOT="$(echo ~)/win-cross/vs2022"
|
||||||
|
|
||||||
export WINE="$(echo ~)/win-cross/wine/bin/wine"
|
export WINE="$(echo ~)/win-cross/wine/bin/wine64"
|
||||||
export WINEDEBUG=-all
|
export WINEDEBUG=-all
|
||||||
|
|
||||||
export MOZ_STUB_INSTALLER=1
|
export MOZ_STUB_INSTALLER=1
|
||||||
|
|||||||
@@ -1,276 +0,0 @@
|
|||||||
# Issue Metrics
|
|
||||||
|
|
||||||
| Metric | Average | Median | 90th percentile |
|
|
||||||
| --- | --- | --- | ---: |
|
|
||||||
| Time to first response | 15:19:48 | 2:42:07 | 1 day, 0:05:54 |
|
|
||||||
| Time to close | 22:10:13 | 4:42:08 | 2 days, 0:56:21 |
|
|
||||||
|
|
||||||
| Metric | Count |
|
|
||||||
| --- | ---: |
|
|
||||||
| Number of items that remain open | 108 |
|
|
||||||
| Number of items closed | 150 |
|
|
||||||
| Total number of items created | 258 |
|
|
||||||
|
|
||||||
| Title | URL | Time to first response | Time to close |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| The right click menu goes beyond the app border sometimes on arch hyprland | https://github.com/zen-browser/desktop/issues/11103 | None | None |
|
|
||||||
| Zen glance doesn't respect --margin-top-fix | https://github.com/zen-browser/desktop/issues/11098 | None | None |
|
|
||||||
| Security info button missing in url bar | https://github.com/zen-browser/desktop/issues/11093 | None | None |
|
|
||||||
| OS dark mode not detected by browser | https://github.com/zen-browser/desktop/issues/11092 | None | None |
|
|
||||||
| Zen menu is somehow showing on the "wrong" side of the app | https://github.com/zen-browser/desktop/issues/11091 | None | None |
|
|
||||||
| Volume is very low in YouTube videos. | https://github.com/zen-browser/desktop/issues/11089 | None | None |
|
|
||||||
| Opening Sidebar by Dragging URL in Compact Mode May Prevent Sidebar from Hiding | https://github.com/zen-browser/desktop/issues/11088 | None | None |
|
|
||||||
| Collapsed sidebar tab icons are misaligned when tabs are overflown | https://github.com/zen-browser/desktop/issues/11087 | 2:13:10 | None |
|
|
||||||
| Screensharing Teams over Zen instantly caused the system to hard crash | https://github.com/zen-browser/desktop/issues/11086 | None | None |
|
|
||||||
| Can't use KeePassXC-Browser in Zen (Flatpak) with KeePassXC (not FlatPak) | https://github.com/zen-browser/desktop/issues/11084 | None | None |
|
|
||||||
| PiP video reproduction makes the tab crash after a while | https://github.com/zen-browser/desktop/issues/11083 | None | None |
|
|
||||||
| Elements above the essentials tabs are in the toolbar instead of the sidebar in compact mode | https://github.com/zen-browser/desktop/issues/11082 | 1:11:28 | None |
|
|
||||||
| Select Tag missing background makes content not visible | https://github.com/zen-browser/desktop/issues/11081 | 15:01:49 | 19:55:32 |
|
|
||||||
| Hovering bookmarks toolbar causes vertical wiggle of website | https://github.com/zen-browser/desktop/issues/11080 | 0:32:11 | None |
|
|
||||||
| Custom Wallpaper on new tab does not loads in any Container | https://github.com/zen-browser/desktop/issues/11079 | 4:25:50 | 4:25:50 |
|
|
||||||
| Unable to activate the option to clear the history without the Zen interface being down. | https://github.com/zen-browser/desktop/issues/11078 | None | None |
|
|
||||||
| Zen sometimes hangs when a context menu or overlay is triggered | https://github.com/zen-browser/desktop/issues/11077 | None | None |
|
|
||||||
| Theme Editor fails to render the colour picker | https://github.com/zen-browser/desktop/issues/11076 | 1:55:40 | 19:38:53 |
|
|
||||||
| Tabs lost when closing main window before Library window | https://github.com/zen-browser/desktop/issues/11073 | None | None |
|
|
||||||
| The topbar doesn't hide in compact when the browser is closed and opening a link from outside | https://github.com/zen-browser/desktop/issues/11070 | None | None |
|
|
||||||
| Essentials tabs are no longer colored to icon accent (zen.theme.essentials-favicon-bg) | https://github.com/zen-browser/desktop/issues/11069 | None | None |
|
|
||||||
| Browser Gets Stuck in workspace. and upon restart deletes all current tabs & history. | https://github.com/zen-browser/desktop/issues/11068 | None | None |
|
|
||||||
| Unloaded tabs logos aren't dimmed | https://github.com/zen-browser/desktop/issues/11065 | None | None |
|
|
||||||
| url bar disappearing and stuttering after last update | https://github.com/zen-browser/desktop/issues/11063 | 1:01:34 | 5:21:04 |
|
|
||||||
| Unable to install any mods from the store / mods do not work anymore | https://github.com/zen-browser/desktop/issues/11062 | None | None |
|
|
||||||
| Page missing space without compact mode | https://github.com/zen-browser/desktop/issues/11060 | None | None |
|
|
||||||
| Unable to drop new tabs when using auto-hide menu | https://github.com/zen-browser/desktop/issues/11059 | None | 0:23:34 |
|
|
||||||
| Window top bar overlaps contents when expanded on hover | https://github.com/zen-browser/desktop/issues/11056 | 2:37:18 | 4:47:35 |
|
|
||||||
| SAVED WEBSITES NOT SHOWING FAVICONS ON STARTUP | https://github.com/zen-browser/desktop/issues/11050 | 5:08:35 | 6:19:52 |
|
|
||||||
| On single toolbar mode shortcut "toggle sidebar's width" doesnt change zen.view.use-single-toolbar, causing you to never be able to not hide sidebar in compact mode | https://github.com/zen-browser/desktop/issues/11049 | None | 2:09:48 |
|
|
||||||
| After every Zen Browser update, the browser automatically redirects all HTTP requests to HTTPS | https://github.com/zen-browser/desktop/issues/11048 | 1 day, 3:16:04 | None |
|
|
||||||
| Sidebar keeps moving when dragging a link to the sidebar in compact mode | https://github.com/zen-browser/desktop/issues/11045 | 1:26:22 | 1:26:22 |
|
|
||||||
| Browser auto force quits when sharing screen on Google meet | https://github.com/zen-browser/desktop/issues/11044 | 1 day, 0:37:45 | None |
|
|
||||||
| bookmark icon missing from address bar. Extenision cannot be pinned to toolbar | https://github.com/zen-browser/desktop/issues/11043 | 0:08:08 | 18:47:26 |
|
|
||||||
| Folder bug because of browser.tabs.groups.enabled was set to true when the first update about folders came out. | https://github.com/zen-browser/desktop/issues/11042 | 6:09:21 | 6:09:21 |
|
|
||||||
| Very confusing behaviour: Zen changes some keyboards keys | https://github.com/zen-browser/desktop/issues/11039 | None | None |
|
|
||||||
| Floating URL bar is off-center in Compact Mode | https://github.com/zen-browser/desktop/issues/11036 | 5:43:02 | 9:06:12 |
|
|
||||||
| severe lag when Compact Tabs mode is enabled | https://github.com/zen-browser/desktop/issues/11035 | None | None |
|
|
||||||
| Pinned/Essentials tabs are not individual for each window on restart | https://github.com/zen-browser/desktop/issues/11034 | 20:23:59 | None |
|
|
||||||
| Issue with toolbar after the update | https://github.com/zen-browser/desktop/issues/11033 | 0:30:05 | 0:30:05 |
|
|
||||||
| Url bar sometimes overlaps page | https://github.com/zen-browser/desktop/issues/11032 | 0:40:02 | None |
|
|
||||||
| Sluggish Scrolling With Winodws 11 Dynamic Refresh Rate | https://github.com/zen-browser/desktop/issues/11030 | 0:36:58 | 2:14:02 |
|
|
||||||
| [Bug] Picture-in-Picture (PiP) icon disappears from the URL bar | https://github.com/zen-browser/desktop/issues/11029 | 2:02:15 | 2 days, 1:05:37 |
|
|
||||||
| Splitter barely visible when Split View + Compact Mode are active | https://github.com/zen-browser/desktop/issues/11027 | 0:11:40 | None |
|
|
||||||
| The new unified panel has significantly affected the dragging link behavior (For example, drag and drop to save bookmarks). | https://github.com/zen-browser/desktop/issues/11026 | None | None |
|
|
||||||
| Nextcloud passwords plugin fails to keep connection to nextcloud | https://github.com/zen-browser/desktop/issues/11025 | None | None |
|
|
||||||
| Extension symbol in toolbar | https://github.com/zen-browser/desktop/issues/11024 | 1:04:53 | None |
|
|
||||||
| bookmark is bugged | https://github.com/zen-browser/desktop/issues/11023 | None | 2:09:24 |
|
|
||||||
| Essential tab background color not adapting to icon color | https://github.com/zen-browser/desktop/issues/11022 | None | None |
|
|
||||||
| Extensions button is missing if Removed from toolbar | https://github.com/zen-browser/desktop/issues/11021 | 0:12:48 | 0:12:48 |
|
|
||||||
| Zen icon not appearing in sidebar in "only sidebar" mode in macOS | https://github.com/zen-browser/desktop/issues/11020 | 1:19:03 | None |
|
|
||||||
| White background websites render as transparent | https://github.com/zen-browser/desktop/issues/11019 | 2:00:20 | 5 days, 10:00:50 |
|
|
||||||
| Extensions menu (and its "jigsaw" button) need to be an option | https://github.com/zen-browser/desktop/issues/11013 | 1:10:36 | 1:10:36 |
|
|
||||||
| sign in with google failing | https://github.com/zen-browser/desktop/issues/11010 | 0:15:42 | None |
|
|
||||||
| Stuttering when playing 4K videos on Bilibili | https://github.com/zen-browser/desktop/issues/11007 | 0:27:17 | 1 day, 17:54:57 |
|
|
||||||
| Cannot access extension icons on sites that have DRM content in version 1.17.2b | https://github.com/zen-browser/desktop/issues/11004 | 1:05:25 | None |
|
|
||||||
| URL bar in a wrong place | https://github.com/zen-browser/desktop/issues/11002 | 1:34:49 | 1:34:49 |
|
|
||||||
| Zen slow on Linux after v1.17b | https://github.com/zen-browser/desktop/issues/11001 | None | 20:41:15 |
|
|
||||||
| Extension flagged by Mozilla as risky display broken | https://github.com/zen-browser/desktop/issues/11000 | 1:46:25 | 1:46:25 |
|
|
||||||
| Title bar of zen browser | https://github.com/zen-browser/desktop/issues/10998 | 0:46:49 | 0:47:07 |
|
|
||||||
| Glance buttons not appearing on the left side | https://github.com/zen-browser/desktop/issues/10997 | 1:06:43 | 1:06:43 |
|
|
||||||
| Compact Mode Sidebar Obfuscats Favorites (Top) in New Window | https://github.com/zen-browser/desktop/issues/10994 | None | 0:10:54 |
|
|
||||||
| Video issues (constant stuttering) On Flatpack version of Zen browser | https://github.com/zen-browser/desktop/issues/10993 | 0:10:08 | 2 days, 8:24:55 |
|
|
||||||
| Update to 1.17.2b wiped the session data | https://github.com/zen-browser/desktop/issues/10992 | 2:11:53 | None |
|
|
||||||
| Zen freezes when an image is copied on Linux | https://github.com/zen-browser/desktop/issues/10991 | 4:55:17 | None |
|
|
||||||
| Toolbar items becomes overflow menu | https://github.com/zen-browser/desktop/issues/10990 | 6:38:06 | 8:17:57 |
|
|
||||||
| Compact mode double toolbar slide over webview not appearing correctly | https://github.com/zen-browser/desktop/issues/10987 | 0:23:29 | 10:55:15 |
|
|
||||||
| Middle clicking on a pinned tab no longer removes it | https://github.com/zen-browser/desktop/issues/10984 | 2:11:56 | 2:11:56 |
|
|
||||||
| Page Reload icon | https://github.com/zen-browser/desktop/issues/10983 | 2:35:26 | 2:35:26 |
|
|
||||||
| v1.17 broke CamelCamelCamel extension | https://github.com/zen-browser/desktop/issues/10982 | 2:42:07 | 2:42:07 |
|
|
||||||
| Closing last tab individually prevents restoring window/session | https://github.com/zen-browser/desktop/issues/10981 | None | None |
|
|
||||||
| Cannot drag image to the left panel when in compact mode | https://github.com/zen-browser/desktop/issues/10979 | 0:30:59 | 6:10:19 |
|
|
||||||
| Suddenly my tabs deleted | https://github.com/zen-browser/desktop/issues/10978 | None | None |
|
|
||||||
| Release Notes tab always opens at the top of the tabs' list | https://github.com/zen-browser/desktop/issues/10976 | 0:01:36 | None |
|
|
||||||
| I cannot use the "hide toolbar" option on compact mode | https://github.com/zen-browser/desktop/issues/10975 | None | 0:12:57 |
|
|
||||||
| Mouse events not firing correctly for items under control buttons when the bar is hidden | https://github.com/zen-browser/desktop/issues/10973 | 0:36:05 | 1 day, 9:12:42 |
|
|
||||||
| Container tab name removed from URL bar | https://github.com/zen-browser/desktop/issues/10972 | 0:16:56 | 1:13:15 |
|
|
||||||
| Extensions (Puzzle Piece) Icon Missing After Update | https://github.com/zen-browser/desktop/issues/10971 | 0:12:24 | 0:28:02 |
|
|
||||||
| Top toolbar in multi-toolbar mode is shown when it shouldn’t | https://github.com/zen-browser/desktop/issues/10970 | None | 2:08:34 |
|
|
||||||
| Middle clicking on pending tab no longer closes it | https://github.com/zen-browser/desktop/issues/10969 | None | 0:01:44 |
|
|
||||||
| Reload button is hidden under menu when it is the only item in the menu | https://github.com/zen-browser/desktop/issues/10968 | None | 0:44:47 |
|
|
||||||
| Compact Mode sidebar is on the bottom of the screen rather than being in the middle. | https://github.com/zen-browser/desktop/issues/10965 | None | 0:08:13 |
|
|
||||||
| Youtube video player cropped in fullscreen | https://github.com/zen-browser/desktop/issues/10964 | None | 0:02:31 |
|
|
||||||
| New Site Control Center renders add-on warnings vertically on top of the rest of the UI | https://github.com/zen-browser/desktop/issues/10963 | None | 0:02:07 |
|
|
||||||
| Media keys (Previous, Pause, Next) don't work | https://github.com/zen-browser/desktop/issues/10962 | 0:01:20 | 6:30:56 |
|
|
||||||
| [UI] Container IDs removed from URL bar | https://github.com/zen-browser/desktop/issues/10961 | 0:09:33 | 0:12:33 |
|
|
||||||
| History | https://github.com/zen-browser/desktop/issues/10960 | 0:22:22 | 0:58:14 |
|
|
||||||
| The toolbar remains visible after following specific steps in compact mode | https://github.com/zen-browser/desktop/issues/10959 | 2:31:24 | None |
|
|
||||||
| New extensions' interface in address bar still broken for some extensions | https://github.com/zen-browser/desktop/issues/10958 | None | 8:26:44 |
|
|
||||||
| Copy current URL pop up doesn't disappear | https://github.com/zen-browser/desktop/issues/10956 | 8:56:54 | 10:51:44 |
|
|
||||||
| The icon for "Enable compact mode" is a duplicate in the sidebar. | https://github.com/zen-browser/desktop/issues/10955 | 10:48:59 | None |
|
|
||||||
| Wrong style on 4 buttons | https://github.com/zen-browser/desktop/issues/10954 | 0:27:06 | 0:27:06 |
|
|
||||||
| Poor formatting in extensions control panel | https://github.com/zen-browser/desktop/issues/10953 | 0:32:14 | 0:32:14 |
|
|
||||||
| New top border line at top of browser application window | https://github.com/zen-browser/desktop/issues/10952 | None | 0:58:56 |
|
|
||||||
| "Hide Top bar" compact mode is greyed out / impossible to select | https://github.com/zen-browser/desktop/issues/10951 | 0:07:47 | 14:26:57 |
|
|
||||||
| Cannot hide "forward" button from toolbar | https://github.com/zen-browser/desktop/issues/10949 | 0:28:05 | 0:28:05 |
|
|
||||||
| Top toolbar now covers up top of webpages | https://github.com/zen-browser/desktop/issues/10948 | 0:34:17 | 14:55:39 |
|
|
||||||
| Missing the Extensions "Jigsaw" icon next to the URL bar. | https://github.com/zen-browser/desktop/issues/10947 | 0:45:52 | 4:36:42 |
|
|
||||||
| Can't place Home button to left upper corner | https://github.com/zen-browser/desktop/issues/10946 | None | None |
|
|
||||||
| All tabs close and disappear when you open a private window | https://github.com/zen-browser/desktop/issues/10945 | None | 1:03:19 |
|
|
||||||
| Youtube Controls Only Partially Visible in Fullscreen Mode | https://github.com/zen-browser/desktop/issues/10944 | 1:21:37 | 1:21:37 |
|
|
||||||
| Sidebar Flickers/Flaps Rapidly When Dragging Text/URL to Window Edge in Compact Mode | https://github.com/zen-browser/desktop/issues/10942 | 2:43:13 | 6 days, 19:36:33 |
|
|
||||||
| Dragging tab out of window opens a new blank window instead of a new tabbed window | https://github.com/zen-browser/desktop/issues/10941 | 0:15:32 | 0:15:32 |
|
|
||||||
| Compact Mode "Hide toolbar" only works with tabs on right | https://github.com/zen-browser/desktop/issues/10940 | 0:25:59 | 0:25:58 |
|
|
||||||
| Floating URL bar not appearing on focus in compact mode | https://github.com/zen-browser/desktop/issues/10938 | 1:53:52 | None |
|
|
||||||
| Extension area layout breaks after switching between toolbar layouts | https://github.com/zen-browser/desktop/issues/10936 | 3:14:21 | 10:14:36 |
|
|
||||||
| No option to revert "new" extensions + site settings menu | https://github.com/zen-browser/desktop/issues/10935 | 3:14:19 | 3:14:19 |
|
|
||||||
| Search bar bug while compact mode on macos | https://github.com/zen-browser/desktop/issues/10934 | 1:01:13 | 1:17:41 |
|
|
||||||
| Tooltips missing for unified panel quick actions | https://github.com/zen-browser/desktop/issues/10933 | None | 4:13:23 |
|
|
||||||
| In collapsed sidebar mode you are no longer able to hide toolbar | https://github.com/zen-browser/desktop/issues/10932 | 1:51:58 | 3:53:59 |
|
|
||||||
| playerctl metadata shows firefox instead of zen browser | https://github.com/zen-browser/desktop/issues/10931 | 8:32:21 | None |
|
|
||||||
| Zen doesn't retrieve correct accent color from OS | https://github.com/zen-browser/desktop/issues/10930 | 4:19:46 | None |
|
|
||||||
| Compact Mode Issue on Windows | https://github.com/zen-browser/desktop/issues/10929 | 3:39:31 | 4:10:59 |
|
|
||||||
| Layout inconsistency between Look and Feel preview and the actual collapsed toolbar | https://github.com/zen-browser/desktop/issues/10928 | 0:30:59 | 5:17:10 |
|
|
||||||
| about:logo has wrong logo | https://github.com/zen-browser/desktop/issues/10926 | None | None |
|
|
||||||
| pinned split view tabs don't have "X" near them on hover | https://github.com/zen-browser/desktop/issues/10924 | None | 5:40:27 |
|
|
||||||
| New extention tab doesnt render right if one of the extentions violate mozilla policy | https://github.com/zen-browser/desktop/issues/10922 | None | 5:16:46 |
|
|
||||||
| Line above URL bar but not sidebar | https://github.com/zen-browser/desktop/issues/10921 | 5:57:13 | 5:57:13 |
|
|
||||||
| New menu for extensions, etc. overflows the window. | https://github.com/zen-browser/desktop/issues/10918 | 0:37:05 | 0:53:30 |
|
|
||||||
| [UI Bug?] Horizontal scrollbar appears in "Looks and Feel" settings on smaller window widths (e.g. 1280px) | https://github.com/zen-browser/desktop/issues/10915 | 3:43:21 | 1 day, 13:46:48 |
|
|
||||||
| 'New tab' button no longer at the top of unpinned tabs | https://github.com/zen-browser/desktop/issues/10914 | 3:19:00 | 11:13:57 |
|
|
||||||
| Top toolbar adopts Transparent Zen mod format in Compact Mode Double Toolbar | https://github.com/zen-browser/desktop/issues/10913 | 3:34:48 | 3:34:48 |
|
|
||||||
| Compact Mode formatting bugs when switching between Toolbar settings | https://github.com/zen-browser/desktop/issues/10912 | 3:58:57 | None |
|
|
||||||
| Compact Mode Collapsed Sidebar on hover endlessly expands | https://github.com/zen-browser/desktop/issues/10911 | None | 4:09:14 |
|
|
||||||
| Compact Mode Sidebar Only won't hide. | https://github.com/zen-browser/desktop/issues/10910 | 3:45:10 | None |
|
|
||||||
| Compact Mode Double Toolbar, Top Toolbar doesn't hide. | https://github.com/zen-browser/desktop/issues/10909 | None | 0:29:10 |
|
|
||||||
| Compact mode hide toolbar option Broken if 'Tabs on Right' | https://github.com/zen-browser/desktop/issues/10908 | 5:35:04 | 5:35:04 |
|
|
||||||
| New extensions' interface in address bar broken for some extensions | https://github.com/zen-browser/desktop/issues/10907 | 0:12:05 | 3 days, 15:02:25 |
|
|
||||||
| Missing tabs when closing and reopening Zen browser with multiple windows | https://github.com/zen-browser/desktop/issues/10906 | 0:09:30 | 0:09:30 |
|
|
||||||
| missing theme/accent settings (linux, flathub) (?) | https://github.com/zen-browser/desktop/issues/10905 | 1:06:10 | 1:06:10 |
|
|
||||||
| Battery consumption | https://github.com/zen-browser/desktop/issues/10903 | 0:29:10 | 0:29:10 |
|
|
||||||
| browser-init-js.patch error while building from zero on arch linux | https://github.com/zen-browser/desktop/issues/10902 | 3:53:18 | None |
|
|
||||||
| Addon popup window broken when no tabs opened | https://github.com/zen-browser/desktop/issues/10900 | None | 1:43:44 |
|
|
||||||
| Udemy Crash | https://github.com/zen-browser/desktop/issues/10898 | None | 0:04:29 |
|
|
||||||
| Text in sidebar becomes unreadable after switching system theme | https://github.com/zen-browser/desktop/issues/10893 | 12:10:14 | 12:11:00 |
|
|
||||||
| Extensions popup failing to render when zen is recently launched | https://github.com/zen-browser/desktop/issues/10892 | 0:06:10 | 0:33:28 |
|
|
||||||
| New tab URL popup doesn’t appear when opening a new tab using Ctrl+T while watching videos in fullscreen | https://github.com/zen-browser/desktop/issues/10891 | 9:44:27 | 15:42:30 |
|
|
||||||
| Zen Browser’s RAM usage on Arch Linux suddenly completely blew up after waking up from sleep (64GB of RAM + 32GB of Zram) | https://github.com/zen-browser/desktop/issues/10889 | 11:05:26 | 4 days, 0:26:42 |
|
|
||||||
| Holy GPU Usage (I have a 6750xt for reference {12GB VRAM} ) | https://github.com/zen-browser/desktop/issues/10888 | 13:36:41 | 5 days, 21:19:18 |
|
|
||||||
| Dragging tabs across multi-screens | https://github.com/zen-browser/desktop/issues/10875 | None | None |
|
|
||||||
| Sidbery Conflict in Zen Browser only | https://github.com/zen-browser/desktop/issues/10871 | None | 2 days, 5:59:58 |
|
|
||||||
| Bookmarks Bar Folders is incorrectly redundantly displayed | https://github.com/zen-browser/desktop/issues/10866 | 2 days, 17:12:01 | None |
|
|
||||||
| Source tarball should include zen locales | https://github.com/zen-browser/desktop/issues/10865 | None | 15:18:10 |
|
|
||||||
| Simplify extension login breaking | https://github.com/zen-browser/desktop/issues/10864 | 0:12:31 | 1:06:05 |
|
|
||||||
| Open site in container sites cannot be added to essentials | https://github.com/zen-browser/desktop/issues/10862 | 1:07:05 | None |
|
|
||||||
| 1password addon integration fails to show unlock window | https://github.com/zen-browser/desktop/issues/10859 | 0:39:20 | None |
|
|
||||||
| duplicated letters or conflict with Vietnamese keyboards | https://github.com/zen-browser/desktop/issues/10858 | 1:29:34 | 1:35:14 |
|
|
||||||
| Creating a space with multiple windows open freezes other windows | https://github.com/zen-browser/desktop/issues/10857 | 8:08:55 | None |
|
|
||||||
| Mozilla services miscredited in user menu | https://github.com/zen-browser/desktop/issues/10854 | None | 4 days, 2:52:29 |
|
|
||||||
| Website's icons not showing if not loaded | https://github.com/zen-browser/desktop/issues/10853 | 0:06:20 | 0:06:20 |
|
|
||||||
| Bookmarks Toolbar is completely blank (flatpak install) | https://github.com/zen-browser/desktop/issues/10852 | 0:58:24 | 2:24:04 |
|
|
||||||
| Closing a tab switches to a particular previously visited tab instead of the immediately previous | https://github.com/zen-browser/desktop/issues/10848 | None | None |
|
|
||||||
| A resize cursor appears. | https://github.com/zen-browser/desktop/issues/10846 | 10:28:06 | None |
|
|
||||||
| Bookmarks Toolbar can not "only show on new tab" | https://github.com/zen-browser/desktop/issues/10845 | 9:18:48 | None |
|
|
||||||
| Sound not working on browser | https://github.com/zen-browser/desktop/issues/10844 | 9:25:58 | None |
|
|
||||||
| Theme issue on the UI | https://github.com/zen-browser/desktop/issues/10835 | None | None |
|
|
||||||
| Zombie processes | https://github.com/zen-browser/desktop/issues/10834 | 0:22:17 | None |
|
|
||||||
| The URL bar flashes too often | https://github.com/zen-browser/desktop/issues/10832 | None | 0:04:01 |
|
|
||||||
| Fixed or anchored website in browser can't be removed | https://github.com/zen-browser/desktop/issues/10828 | 0:15:40 | 6:35:29 |
|
|
||||||
| The media controls at the bottom overlap important elements. | https://github.com/zen-browser/desktop/issues/10824 | 9:33:17 | 17:48:58 |
|
|
||||||
| [Twilight] Compact mode button causing top toolbar to not hide/to not appear when hovering | https://github.com/zen-browser/desktop/issues/10821 | None | 17:59:30 |
|
|
||||||
| the top bar is not functional as expexted. | https://github.com/zen-browser/desktop/issues/10820 | 0:22:50 | 14:40:32 |
|
|
||||||
| Browser Screen Goes Blank (Them color ) Randomly –No UI Visible, Audio Still play . | https://github.com/zen-browser/desktop/issues/10817 | None | None |
|
|
||||||
| Sidebar Gets Stuck After Interacting With an Exntension in Compact Mode | https://github.com/zen-browser/desktop/issues/10812 | 2:15:35 | 10:54:25 |
|
|
||||||
| website setting lost | https://github.com/zen-browser/desktop/issues/10811 | None | None |
|
|
||||||
| Scrolling cause GPU spikes | https://github.com/zen-browser/desktop/issues/10810 | 0:02:36 | 3:39:42 |
|
|
||||||
| No such native application org.gnome.chrome_gnome_shell | https://github.com/zen-browser/desktop/issues/10806 | 2:20:05 | None |
|
|
||||||
| keep crashing | https://github.com/zen-browser/desktop/issues/10804 | 1 day, 0:05:54 | None |
|
|
||||||
| Workspace-aware restore closed tab behavior for reopening tabs | https://github.com/zen-browser/desktop/issues/10803 | 1 day, 20:48:51 | 1 day, 20:48:51 |
|
|
||||||
| After activation "Zen will never remember history" all toolbars are black and the font color is also black | https://github.com/zen-browser/desktop/issues/10802 | 9:08:32 | None |
|
|
||||||
| Fullscreen mode doesn't hide toolbar and sidebar | https://github.com/zen-browser/desktop/issues/10800 | 7:38:33 | 7:38:33 |
|
|
||||||
| DOH: Zen loose connectivity when network changes | https://github.com/zen-browser/desktop/issues/10799 | None | None |
|
|
||||||
| Large Memory Leak Issue (zen.exe not properly exiting) | https://github.com/zen-browser/desktop/issues/10797 | 10:46:25 | 10:46:25 |
|
|
||||||
| Absolutely broken compact mode 1.17t | https://github.com/zen-browser/desktop/issues/10796 | 10:56:37 | 1 day, 11:24:34 |
|
|
||||||
| I am being randomly logged out of websites | https://github.com/zen-browser/desktop/issues/10792 | None | None |
|
|
||||||
| 1Password desktop app integration not working in Zen Browser | https://github.com/zen-browser/desktop/issues/10788 | 0:44:13 | 0:44:13 |
|
|
||||||
| [Bug] WebRender content becomes blurry at 5120x1440 with NVIDIA eGPU on Linux (X11) - Upstream Firefox has this issue too but not as badly | https://github.com/zen-browser/desktop/issues/10787 | None | None |
|
|
||||||
| Tab Icons not rendering for certain tabs | https://github.com/zen-browser/desktop/issues/10782 | 0:09:03 | 0:09:03 |
|
|
||||||
| Dragging sidebar moves the window | https://github.com/zen-browser/desktop/issues/10781 | 1:56:10 | 1:56:10 |
|
|
||||||
| blinking caret bug | https://github.com/zen-browser/desktop/issues/10780 | 3:09:48 | 3:09:48 |
|
|
||||||
| Freezing youtube videos when i change screens | https://github.com/zen-browser/desktop/issues/10779 | None | None |
|
|
||||||
| Browser Icons Not Showing on Toolbar or Favorites in KDE Plasma on Fedora Linux | https://github.com/zen-browser/desktop/issues/10778 | None | None |
|
|
||||||
| AUR version of Zen Browser glitches/pauses continuously | https://github.com/zen-browser/desktop/issues/10777 | 12:31:55 | None |
|
|
||||||
| When tab changes while sub-folder is closing, does not fold the tab opened | https://github.com/zen-browser/desktop/issues/10772 | 9:29:58 | 9:29:58 |
|
|
||||||
| Green artifacts appear on the scrollbar while scrolling some webpages | https://github.com/zen-browser/desktop/issues/10766 | 6:41:23 | None |
|
|
||||||
| no newtab wallpaper apart from Default Workspace with no set profile container. | https://github.com/zen-browser/desktop/issues/10764 | 1:01:42 | 5:12:31 |
|
|
||||||
| Zen is slow to update and restart on macOS | https://github.com/zen-browser/desktop/issues/10763 | None | None |
|
|
||||||
| Layout issue: Preventing window from closing, minimizing, or resizing | https://github.com/zen-browser/desktop/issues/10762 | None | 18 days, 0:27:20 |
|
|
||||||
| Url bar overflow when click fullscreen | https://github.com/zen-browser/desktop/issues/10760 | None | None |
|
|
||||||
| Updates Failing | https://github.com/zen-browser/desktop/issues/10759 | 1 day, 9:15:55 | 1 day, 10:06:37 |
|
|
||||||
| Youtube video playback noticeably dropping frames | https://github.com/zen-browser/desktop/issues/10756 | 7:33:59 | None |
|
|
||||||
| Some websites' background is missing, uses Zen's theme color instead | https://github.com/zen-browser/desktop/issues/10755 | None | 0:02:35 |
|
|
||||||
| Toolbar History icon nonfunctional | https://github.com/zen-browser/desktop/issues/10752 | 20:34:15 | None |
|
|
||||||
| Video and audio playback error after recent pacman update | https://github.com/zen-browser/desktop/issues/10751 | None | 3:41:57 |
|
|
||||||
| Twitch.tv Login Issue on Zen Browser | https://github.com/zen-browser/desktop/issues/10750 | 5:49:14 | 1 day, 1:42:41 |
|
|
||||||
| Missing translations | https://github.com/zen-browser/desktop/issues/10749 | 3:28:20 | None |
|
|
||||||
| Passbolt Password Manager doesn't work properly | https://github.com/zen-browser/desktop/issues/10748 | 12:48:48 | 12:48:48 |
|
|
||||||
| Update are broken on macos since 1.16.4b | https://github.com/zen-browser/desktop/issues/10746 | 2 days, 16:23:56 | None |
|
|
||||||
| Blank Context Menu | https://github.com/zen-browser/desktop/issues/10745 | 10:19:37 | 11:46:43 |
|
|
||||||
| Cant load beehiv login page | https://github.com/zen-browser/desktop/issues/10744 | 14:48:10 | 14:48:10 |
|
|
||||||
| Ctrl+Shift+T after deleting a folder breaks Zen | https://github.com/zen-browser/desktop/issues/10743 | None | None |
|
|
||||||
| Settings: Search -> Address bar with browsing history negates open tabs selection | https://github.com/zen-browser/desktop/issues/10741 | None | None |
|
|
||||||
| NGINX 404 of some sites | https://github.com/zen-browser/desktop/issues/10740 | 3:51:13 | 18:34:43 |
|
|
||||||
| no pop up edit bookmark pages after triggered with 1) shortcut and 2) star icon after right click. setting "Sidebar only" of the 3 sidebar modes | https://github.com/zen-browser/desktop/issues/10738 | 4 days, 5:09:44 | 16 days, 22:20:24 |
|
|
||||||
| Sidebar resize issue when dragging the cursor beyond smallest size | https://github.com/zen-browser/desktop/issues/10737 | 1:03:24 | None |
|
|
||||||
| Can't access extensions menu from New Tab | https://github.com/zen-browser/desktop/issues/10733 | 1:46:53 | 2 days, 1:20:18 |
|
|
||||||
| Regular window tabs lost on closing if Incognito window is open | https://github.com/zen-browser/desktop/issues/10732 | 1:48:17 | 2:00:03 |
|
|
||||||
| Nested folders go back to root of workspace when opening Zen. | https://github.com/zen-browser/desktop/issues/10730 | 3:57:00 | None |
|
|
||||||
| Youtube videoplay laggy | https://github.com/zen-browser/desktop/issues/10729 | 6:03:54 | 2 days, 2:00:09 |
|
|
||||||
| Stay on page doesn't work in pinned/essential tabs | https://github.com/zen-browser/desktop/issues/10728 | None | None |
|
|
||||||
| Touch Keyboard Does Not Show | https://github.com/zen-browser/desktop/issues/10727 | 18 days, 12:51:30 | None |
|
|
||||||
| No page info in compact mode if clicked on URL | https://github.com/zen-browser/desktop/issues/10724 | None | 1:10:01 |
|
|
||||||
| Search Bar Problem | https://github.com/zen-browser/desktop/issues/10723 | 3:29:09 | 19:52:36 |
|
|
||||||
| Can't disable Hide Tab bar | https://github.com/zen-browser/desktop/issues/10722 | 0:12:09 | 2:23:39 |
|
|
||||||
| Compact Mode - Customize Toolbar - Sidebar cannot have Items | https://github.com/zen-browser/desktop/issues/10721 | 4:31:48 | 4:31:48 |
|
|
||||||
| [macOS] File upload dialog freezes Zen Browser for several seconds | https://github.com/zen-browser/desktop/issues/10719 | None | 1:29:55 |
|
|
||||||
| Mouse hover breaks Ctrl + Tab (tab switching) | https://github.com/zen-browser/desktop/issues/10715 | 4 days, 19:04:17 | 5 days, 4:09:28 |
|
|
||||||
| Spotify not working after updating to 1.16.3b | https://github.com/zen-browser/desktop/issues/10714 | 0:12:47 | 2:11:45 |
|
|
||||||
| Cursor dissapears in most online text editors | https://github.com/zen-browser/desktop/issues/10713 | 5:37:12 | None |
|
|
||||||
| Tabs dont close | https://github.com/zen-browser/desktop/issues/10710 | None | None |
|
|
||||||
| Address Bar opens on keypress right after starting zen | https://github.com/zen-browser/desktop/issues/10709 | None | None |
|
|
||||||
| Search bar wont fully disappear when trying to close it | https://github.com/zen-browser/desktop/issues/10708 | 9:51:49 | 9:51:49 |
|
|
||||||
| [Twilight] Tabs' area is reduced when enabling compact mode in collapsed toolbars layout | https://github.com/zen-browser/desktop/issues/10706 | 15:58:04 | 15:58:04 |
|
|
||||||
| Is not possible expand de tabs side bar | https://github.com/zen-browser/desktop/issues/10705 | 0:19:09 | 12:56:28 |
|
|
||||||
| Missing tab navigation keyboard shortcut | https://github.com/zen-browser/desktop/issues/10704 | 2:47:17 | 1 day, 1:48:51 |
|
|
||||||
| Switching workspace hotkey slow to repeat. | https://github.com/zen-browser/desktop/issues/10703 | 4:59:37 | None |
|
|
||||||
| DevTools warning: connected browser newer than Zen (unsupported setup message) | https://github.com/zen-browser/desktop/issues/10702 | None | 0:07:32 |
|
|
||||||
| - [Bug] High Memory & Disk Consumption on Snapdragon X Plus Device | https://github.com/zen-browser/desktop/issues/10701 | None | None |
|
|
||||||
| Youtube Live Streams Are Not Working After The Update | https://github.com/zen-browser/desktop/issues/10698 | 3:17:57 | 1 day, 3:35:02 |
|
|
||||||
| Very low performance | https://github.com/zen-browser/desktop/issues/10695 | 1:40:48 | 1:40:48 |
|
|
||||||
| Can you fucing fix the ctrashing???? | https://github.com/zen-browser/desktop/issues/10693 | 0:42:11 | 3:45:23 |
|
|
||||||
| Strange Behaviour with Context Menu Clicks | https://github.com/zen-browser/desktop/issues/10691 | 6:58:32 | None |
|
|
||||||
| Can't play DRM content on the latest release 1.16.3b | https://github.com/zen-browser/desktop/issues/10689 | 15:28:49 | None |
|
|
||||||
| On macOS, workspace swipe actions require "Swipe between pages" to be enabled in system settings | https://github.com/zen-browser/desktop/issues/10687 | None | None |
|
|
||||||
| macOS Altcodes / Modifier Keys Cause Keyboard Shortcut Issues | https://github.com/zen-browser/desktop/issues/10686 | 11 days, 13:05:50 | None |
|
|
||||||
| Mute button simply stopped functioning. | https://github.com/zen-browser/desktop/issues/10685 | None | None |
|
|
||||||
| Linux: 1Password desktop integration fails for Flatpak and Tarball installs | https://github.com/zen-browser/desktop/issues/10684 | None | None |
|
|
||||||
| Entire Program Constantly Crashes With No Discernible Reproduction Method, Making it Unusable | https://github.com/zen-browser/desktop/issues/10683 | 4:17:45 | 1 day, 10:38:49 |
|
|
||||||
| URL Bar appears cut off and onto the side (Floating URL Bar Issue) | https://github.com/zen-browser/desktop/issues/10682 | 1:31:06 | 0:02:30 |
|
|
||||||
| All tabs keep crashing on Windows | https://github.com/zen-browser/desktop/issues/10681 | 1 day, 7:25:22 | None |
|
|
||||||
| Failure to Update Zen Browser from Version 1.16.1b-1 to 1.16.2b-1 | https://github.com/zen-browser/desktop/issues/10678 | 2:02:51 | 5:04:58 |
|
|
||||||
| Cannot set hotkey for "Stop Loading" (Browser:Stop). | https://github.com/zen-browser/desktop/issues/10677 | 2 days, 0:55:20 | 2 days, 0:55:19 |
|
|
||||||
| Zen has suddenly overriden default Bitwarden keyboard shortcut and even when unbound it cannot be used for bitwarden | https://github.com/zen-browser/desktop/issues/10676 | None | None |
|
|
||||||
| Zen Browser blocks Macbook from sleep | https://github.com/zen-browser/desktop/issues/10673 | None | None |
|
|
||||||
| Cannot select text in URL bar by dragging mouse | https://github.com/zen-browser/desktop/issues/10671 | None | 1 day, 20:37:27 |
|
|
||||||
| Bookmarks bar partially obscured by sidebar | https://github.com/zen-browser/desktop/issues/10667 | 19 days, 23:45:50 | None |
|
|
||||||
| Browser freezes when tab is opened by external app with workspace switching enabled | https://github.com/zen-browser/desktop/issues/10666 | 1 day, 1:33:52 | None |
|
|
||||||
| The bookmarks bar disappears in full screen mode | https://github.com/zen-browser/desktop/issues/10665 | 18:54:47 | 20:41:21 |
|
|
||||||
| Websites rendering broken for me in 1.16 (fixed but reporting for clarity) | https://github.com/zen-browser/desktop/issues/10664 | None | None |
|
|
||||||
| cmd + option + M interferes with macOS cmd + option + H + M global command | https://github.com/zen-browser/desktop/issues/10663 | None | None |
|
|
||||||
| Zen freezes for ~3 seconds when downloading a file | https://github.com/zen-browser/desktop/issues/10657 | 18:33:18 | None |
|
|
||||||
| Twitch Video Stuttering | https://github.com/zen-browser/desktop/issues/10653 | 1 day, 0:24:44 | None |
|
|
||||||
| Recent Update Made Zen crash when using NVIDIA HW Acceleration (X11, Linux) | https://github.com/zen-browser/desktop/issues/10652 | 5 days, 18:32:13 | None |
|
|
||||||
| Search bar does not hide and stays stuck on screen | https://github.com/zen-browser/desktop/issues/10650 | 0:10:53 | 2:43:42 |
|
|
||||||
| browser stutter/halts/unresponsive | https://github.com/zen-browser/desktop/issues/10649 | 11:29:19 | None |
|
|
||||||
| Issue with `1.16.2b-1` | https://github.com/zen-browser/desktop/issues/10648 | 6:46:15 | 6:46:15 |
|
|
||||||
| Zen Sync not working | https://github.com/zen-browser/desktop/issues/10647 | 1 day, 7:52:54 | 12 days, 4:07:32 |
|
|
||||||
| Stability issue: random crashes after v1.16.2b update | https://github.com/zen-browser/desktop/issues/10646 | 3:44:53 | 10:49:23 |
|
|
||||||
|
|
||||||
_This report was generated with the [Issue Metrics Action](https://github.com/github/issue-metrics)_
|
|
||||||
Search query used to find these items: `repo:zen-browser/desktop is:issue created:2025-10-01..2025-10-31`
|
|
||||||
@@ -304,4 +304,4 @@ zen-devtools-toggle-performance-shortcut = 성능 탭 전환
|
|||||||
zen-devtools-toggle-storage-shortcut = 저장소 탭 전환
|
zen-devtools-toggle-storage-shortcut = 저장소 탭 전환
|
||||||
zen-devtools-toggle-dom-shortcut = DOM 탭 전환
|
zen-devtools-toggle-dom-shortcut = DOM 탭 전환
|
||||||
zen-devtools-toggle-accessibility-shortcut = 접근성 탭 전환
|
zen-devtools-toggle-accessibility-shortcut = 접근성 탭 전환
|
||||||
zen-close-all-unpinned-tabs-shortcut = 모든 고정되지 않은 탭 닫기
|
zen-close-all-unpinned-tabs-shortcut = Close All Unpinned Tabs
|
||||||
|
|||||||
@@ -63,8 +63,8 @@ zen-generic-next = 다음
|
|||||||
# These labels will be used for the site data panel settings
|
# These labels will be used for the site data panel settings
|
||||||
zen-site-data-setting-allow = 허용됨
|
zen-site-data-setting-allow = 허용됨
|
||||||
zen-site-data-setting-block = 금지됨
|
zen-site-data-setting-block = 금지됨
|
||||||
zen-site-data-protections-enabled = 활성화됨
|
zen-site-data-protections-enabled = Enabled
|
||||||
zen-site-data-protections-disabled = 비활성화됨
|
zen-site-data-protections-disabled = Disabled
|
||||||
zen-site-data-setting-cross-site = 사이트 간 공유 쿠키
|
zen-site-data-setting-cross-site = 사이트 간 공유 쿠키
|
||||||
zen-site-data-security-info-extension =
|
zen-site-data-security-info-extension =
|
||||||
.label = 확장
|
.label = 확장
|
||||||
@@ -79,13 +79,13 @@ zen-site-data-get-addons =
|
|||||||
zen-site-data-site-settings =
|
zen-site-data-site-settings =
|
||||||
.label = 모든 사이트 설정
|
.label = 모든 사이트 설정
|
||||||
zen-site-data-header-share =
|
zen-site-data-header-share =
|
||||||
.tooltiptext = 이 페이지 공유
|
.tooltiptext = Share This Page
|
||||||
zen-site-data-header-reader-mode =
|
zen-site-data-header-reader-mode =
|
||||||
.tooltiptext = 읽기 모드 켜기
|
.tooltiptext = Enter Reader Mode
|
||||||
zen-site-data-header-screenshot =
|
zen-site-data-header-screenshot =
|
||||||
.tooltiptext = 화면 캡쳐
|
.tooltiptext = Take a Screenshot
|
||||||
zen-site-data-header-bookmark =
|
zen-site-data-header-bookmark =
|
||||||
.tooltiptext = 이 페이지 북마크
|
.tooltiptext = Bookmark This Page
|
||||||
zen-urlbar-copy-url-button =
|
zen-urlbar-copy-url-button =
|
||||||
.tooltiptext = URL 복사
|
.tooltiptext = URL 복사
|
||||||
zen-site-data-setting-site-protection = 추적 보호
|
zen-site-data-setting-site-protection = 추적 보호
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ zen-workspaces-delete-workspace-title = 워크스페이스를 삭제하시겠습
|
|||||||
zen-workspaces-delete-workspace-body = 정말 { $name }을 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다.
|
zen-workspaces-delete-workspace-body = 정말 { $name }을 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다.
|
||||||
# Note that the html tag MUST not be changed or removed, as it is used to better
|
# Note that the html tag MUST not be changed or removed, as it is used to better
|
||||||
# display the shortcut in the toast notification.
|
# display the shortcut in the toast notification.
|
||||||
zen-workspaces-close-all-unpinned-tabs-toast = 탭을 닫았습니다! 되돌리려면 <span>{ $shortcut }</span>을 사용하세요.
|
zen-workspaces-close-all-unpinned-tabs-toast = Tabs Closed! Use <span>{ $shortcut }</span> to undo.
|
||||||
zen-workspaces-close-all-unpinned-tabs-title =
|
zen-workspaces-close-all-unpinned-tabs-title =
|
||||||
.label = 탭 정리
|
.label = Clear
|
||||||
.tooltiptext = 고정되지 않은 모든 탭을 닫습니다
|
.tooltiptext = Close all unpinned tabs
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ sync-engine-workspaces =
|
|||||||
.label = Darbo sritys
|
.label = Darbo sritys
|
||||||
.tooltiptext = Sinchronizuokite savo darbo sritis tarp įrenginių
|
.tooltiptext = Sinchronizuokite savo darbo sritis tarp įrenginių
|
||||||
.accesskey = W
|
.accesskey = W
|
||||||
zen-glance-title = Spartusis pažiūrėjimas
|
zen-glance-title = Greitasis pažiūrėjimas
|
||||||
zen-glance-header = Bendrieji sparčiojo pažiūrėjimo nustatymai
|
zen-glance-header = Bendrieji greitojo pažiūrėjimo nustatymai
|
||||||
zen-glance-description = Gaukite sparčią savo nuorodų apžvalgą neatverdami jų naujoje kortelėje.
|
zen-glance-description = Gaukite greitą nuorodų apžvalgą neatidarydami jų naujoje kortelėje
|
||||||
zen-glance-trigger-label = Paleidimo būdas
|
zen-glance-trigger-label = Paleidimo būdas
|
||||||
zen-glance-enabled =
|
zen-glance-enabled =
|
||||||
.label = Įjungti spartų pažiūrėjimą
|
.label = Įjungti greitą pažiūrėjimą
|
||||||
zen-glance-trigger-ctrl-click =
|
zen-glance-trigger-ctrl-click =
|
||||||
.label = Vald + spausti
|
.label = Vald + spausti
|
||||||
zen-glance-trigger-alt-click =
|
zen-glance-trigger-alt-click =
|
||||||
@@ -29,15 +29,15 @@ zen-glance-trigger-alt-click =
|
|||||||
zen-glance-trigger-shift-click =
|
zen-glance-trigger-shift-click =
|
||||||
.label = Lyg2 + spausti
|
.label = Lyg2 + spausti
|
||||||
zen-glance-trigger-meta-click =
|
zen-glance-trigger-meta-click =
|
||||||
.label = „Meta“ (komanda) + spausti
|
.label = Meta (Komanda) + spausti
|
||||||
zen-look-and-feel-compact-view-header = Rodyti kompaktiniame rodinyje
|
zen-look-and-feel-compact-view-header = Rodyti kompaktiniame rodinyje
|
||||||
zen-look-and-feel-compact-view-description = Rodyti tik tas įrankių juostas, kurias naudojate.
|
zen-look-and-feel-compact-view-description = Rodyti tik tas įrankių juostas, kurias naudojate!
|
||||||
zen-look-and-feel-compact-view-enabled =
|
zen-look-and-feel-compact-view-enabled =
|
||||||
.label = Įjungti „{ -brand-short-name }“ kompaktinį režimą
|
.label = Įjungti „{ -brand-short-name }“ kompaktinį režimą
|
||||||
zen-look-and-feel-compact-view-top-toolbar =
|
zen-look-and-feel-compact-view-top-toolbar =
|
||||||
.label = Slėpti viršutinę įrankių juostą ir kompaktiniu režimu
|
.label = Slėpti viršutinę įrankių juostą ir kompaktiniu režimu
|
||||||
zen-look-and-feel-compact-toolbar-flash-popup =
|
zen-look-and-feel-compact-toolbar-flash-popup =
|
||||||
.label = Trumpai padaryti, kad įrankių juosta iškiltų perjungiant arba atidarant naujas korteles kompaktiniu režimu
|
.label = Trumpai padaryti, kad įrankių juosta iškyltų perjungiant arba atidarant naujas korteles kompaktiniu režimu
|
||||||
pane-zen-tabs-title = Kortelių tvarkymas
|
pane-zen-tabs-title = Kortelių tvarkymas
|
||||||
category-zen-workspaces =
|
category-zen-workspaces =
|
||||||
.tooltiptext = { pane-zen-tabs-title }
|
.tooltiptext = { pane-zen-tabs-title }
|
||||||
@@ -50,29 +50,29 @@ zen-workspace-continue-where-left-off =
|
|||||||
.label = Tęskite, kur baigėte
|
.label = Tęskite, kur baigėte
|
||||||
pane-zen-pinned-tab-manager-title = Prisegtos kortelės
|
pane-zen-pinned-tab-manager-title = Prisegtos kortelės
|
||||||
zen-pinned-tab-manager-header = Bendrieji prisegtų kortelių nustatymai
|
zen-pinned-tab-manager-header = Bendrieji prisegtų kortelių nustatymai
|
||||||
zen-pinned-tab-manager-description = Tvarkykite papildomą prisegtų kortelių elgseną.
|
zen-pinned-tab-manager-description = Tvarkykite papildomą prisegtų kortelių elgseną
|
||||||
zen-pinned-tab-manager-restore-pinned-tabs-to-pinned-url =
|
zen-pinned-tab-manager-restore-pinned-tabs-to-pinned-url =
|
||||||
.label = Atkurti prisegtas korteles į jų originalų prisegtą URL paleidimo metu
|
.label = Atkurti prisegtas korteles į jų originalų prisegtą URL paleidimo metu
|
||||||
zen-pinned-tab-manager-container-specific-essentials-enabled =
|
zen-pinned-tab-manager-container-specific-essentials-enabled =
|
||||||
.label = Įjungti konkrečiam konteineriui būtinuosius
|
.label = Įjungti konkrečiam konteineriui būtinuosius
|
||||||
zen-pinned-tab-manager-close-shortcut-behavior-label = Užvėrimo kortelę sparčiųjų klavišų elgsena
|
zen-pinned-tab-manager-close-shortcut-behavior-label = Užverti kortelę sparčiųjų klavišų elgsena
|
||||||
zen-pinned-tab-manager-reset-unload-switch-close-shortcut-option =
|
zen-pinned-tab-manager-reset-unload-switch-close-shortcut-option =
|
||||||
.label = Atkurti URL, iškelti ir perjungti į sekančią kortelę
|
.label = Atkurti URL, iškelti ir perjungti į kitą kortelę
|
||||||
zen-pinned-tab-manager-unload-switch-close-shortcut-option =
|
zen-pinned-tab-manager-unload-switch-close-shortcut-option =
|
||||||
.label = Iškelti ir perjungti į sekančią kortelę
|
.label = Iškelti ir perjungti į kitą kortelę
|
||||||
zen-pinned-tab-manager-reset-switch-close-shortcut-option =
|
zen-pinned-tab-manager-reset-switch-close-shortcut-option =
|
||||||
.label = Atkurti URL ir perjungti į sekančią kortelę
|
.label = Atkurti URL ir perjungti į kitą kortelę
|
||||||
zen-pinned-tab-manager-switch-close-shortcut-option =
|
zen-pinned-tab-manager-switch-close-shortcut-option =
|
||||||
.label = Perjungti į sekančią kortelę
|
.label = Perjungti į kitą kortelę
|
||||||
zen-pinned-tab-manager-reset-close-shortcut-option =
|
zen-pinned-tab-manager-reset-close-shortcut-option =
|
||||||
.label = Atkurti URL
|
.label = Atkurti URL
|
||||||
zen-pinned-tab-manager-close-close-shortcut-option =
|
zen-pinned-tab-manager-close-close-shortcut-option =
|
||||||
.label = Užverti kortelę
|
.label = Užverti kortelę
|
||||||
pane-zen-workspaces-header = Darbo sritys
|
pane-zen-workspaces-header = Darbo sritys
|
||||||
zen-settings-workspaces-header = Bendrieji darbo sričių nustatymai
|
zen-settings-workspaces-header = Bendrieji darbo sričių nustatymai
|
||||||
zen-settings-workspaces-description = Su darbo sritimis galite vienu metu atlikti kelias naršymo seansus.
|
zen-settings-workspaces-description = Su darbo sritimis galite vienu metu atlikti kelias naršymo seansus!
|
||||||
zen-settings-workspaces-enabled =
|
zen-settings-workspaces-enabled =
|
||||||
.label = Įjungti darbo sritis
|
.label = Įjungti darbo sritis (eksperimentinė)
|
||||||
zen-settings-workspaces-hide-default-container-indicator =
|
zen-settings-workspaces-hide-default-container-indicator =
|
||||||
.label = Slėpti numatytojo konteinerio indikatorių kortelių juostoje
|
.label = Slėpti numatytojo konteinerio indikatorių kortelių juostoje
|
||||||
zen-key-unsaved = Neįrašytas spartusis klavišas! Iš naujo jį įvedę, paspauskite grįžimo klavišą.
|
zen-key-unsaved = Neįrašytas spartusis klavišas! Iš naujo jį įvedę, paspauskite grįžimo klavišą.
|
||||||
@@ -80,18 +80,18 @@ zen-key-conflict = Konfliktuoja su „{ $group }“ -> „{ $shortcut }“
|
|||||||
pane-zen-theme-title = Temų nustatymai
|
pane-zen-theme-title = Temų nustatymai
|
||||||
zen-vertical-tabs-title = Šoninė juosta ir kortelių išdėstymas
|
zen-vertical-tabs-title = Šoninė juosta ir kortelių išdėstymas
|
||||||
zen-vertical-tabs-header = Vertikalios kortelės
|
zen-vertical-tabs-header = Vertikalios kortelės
|
||||||
zen-vertical-tabs-description = Tvarkykite korteles vertikaliame išdėstyme.
|
zen-vertical-tabs-description = Tvarkykite korteles vertikaliame išdėstyme
|
||||||
zen-vertical-tabs-show-expand-button =
|
zen-vertical-tabs-show-expand-button =
|
||||||
.label = Rodyti išskleidimo mygtuką
|
.label = Rodyti išskleidimo mygtuką
|
||||||
zen-vertical-tabs-newtab-on-tab-list =
|
zen-vertical-tabs-newtab-on-tab-list =
|
||||||
.label = Rodyti naujos kortelės mygtuką kortelių sąraše
|
.label = Rodyti naujos kortelės mygtuką kortelių sąraše
|
||||||
zen-vertical-tabs-newtab-top-button-up =
|
zen-vertical-tabs-newtab-top-button-up =
|
||||||
.label = Perkelti naujos kortelės mygtuką į viršų
|
.label = Perkelti naujos kortelės mygtuką į viršų
|
||||||
zen-vertical-tabs-expand-tabs-by-default = Išskleisti korteles pagal numatytąją
|
zen-vertical-tabs-expand-tabs-by-default = Išskleisti korteles pagal numatytąją nustatymą
|
||||||
zen-vertical-tabs-dont-expand-tabs-by-default = Neišskleisti kortelių pagal numatytąją
|
zen-vertical-tabs-dont-expand-tabs-by-default = Neišskleisti kortelių pagal numatytąją nustatymą
|
||||||
zen-vertical-tabs-expand-tabs-on-hover = Išskleisti korteles užvedus (neveikia kompaktiniame režime)
|
zen-vertical-tabs-expand-tabs-on-hover = Išskleisti korteles užvedus (neveikia kompaktiniame režime)
|
||||||
zen-vertical-tabs-expand-tabs-header = Kaip išskleisti korteles
|
zen-vertical-tabs-expand-tabs-header = Kaip išskleisti korteles
|
||||||
zen-vertical-tabs-expand-tabs-description = Pasirinkite, kaip išskleisti kortelės šoninėje juostoje.
|
zen-vertical-tabs-expand-tabs-description = Pasirinkite, kaip išskleisti kortelės šoninėje juostoje
|
||||||
zen-theme-marketplace-header = „Zen“ modifikacijos
|
zen-theme-marketplace-header = „Zen“ modifikacijos
|
||||||
zen-theme-disable-all-enabled =
|
zen-theme-disable-all-enabled =
|
||||||
.title = Išjungti visus modifikacijas
|
.title = Išjungti visus modifikacijas
|
||||||
@@ -128,10 +128,10 @@ pane-zen-marketplace-title = „Zen“ modifikacijos
|
|||||||
zen-themes-auto-update =
|
zen-themes-auto-update =
|
||||||
.label = Automatiškai atnaujinti įdiegtas modifikacijas paleidimo metu
|
.label = Automatiškai atnaujinti įdiegtas modifikacijas paleidimo metu
|
||||||
zen-settings-workspaces-force-container-tabs-to-workspace =
|
zen-settings-workspaces-force-container-tabs-to-workspace =
|
||||||
.label = Perjungti į darbo sritį, kurioje konteineris nustatytas kaip numatytasis, atveriant konteinerio korteles
|
.label = Perjungti į darbo sritį, kurioje konteineris nustatytas kaip numatytasis, atidarant konteinerio korteles
|
||||||
zen-theme-marketplace-link = Aplankyti parduotuvę
|
zen-theme-marketplace-link = Aplankyti parduotuvę
|
||||||
zen-dark-theme-styles-header = Tamsios temos stiliai
|
zen-dark-theme-styles-header = Tamsios temos stiliai
|
||||||
zen-dark-theme-styles-description = Tinkinkite tamsią temą pagal savo poreikius.
|
zen-dark-theme-styles-description = Tinkinkite tamsią temą pagal savo poreikius
|
||||||
zen-dark-theme-styles-amoled = Naktinė tema
|
zen-dark-theme-styles-amoled = Naktinė tema
|
||||||
zen-dark-theme-styles-default = Numatytoji tamsi tema
|
zen-dark-theme-styles-default = Numatytoji tamsi tema
|
||||||
zen-dark-theme-styles-colorful = Spalvinga tamsi tema
|
zen-dark-theme-styles-colorful = Spalvinga tamsi tema
|
||||||
@@ -153,13 +153,13 @@ category-zen-CKS =
|
|||||||
.tooltiptext = { pane-zen-CKS-title }
|
.tooltiptext = { pane-zen-CKS-title }
|
||||||
pane-settings-CKS-title = „{ -brand-short-name }“ klaviatūros spartieji klavišai
|
pane-settings-CKS-title = „{ -brand-short-name }“ klaviatūros spartieji klavišai
|
||||||
zen-settings-CKS-header = Tinkinkite klaviatūros sparčiuosius klavišus
|
zen-settings-CKS-header = Tinkinkite klaviatūros sparčiuosius klavišus
|
||||||
zen-settings-CKS-description = Keiskite numatytąsias klaviatūros sparčiąsias klavišus pagal savo pageidavimus ir patobulinkite naršymo patirtį.
|
zen-settings-CKS-description = Keiskite numatytąsias klaviatūros sparčiąsias klavišus pagal savo pageidavimus ir patobulinkite naršymo potyrį
|
||||||
zen-settings-CKS-disable-firefox =
|
zen-settings-CKS-disable-firefox =
|
||||||
.label = Išjungti „{ -brand-short-name }“ numatytuosius klaviatūros sparčiuosius klavišus
|
.label = Išjungti „{ -brand-short-name }“ numatytuosius klaviatūros sparčiuosius klavišus
|
||||||
zen-settings-CKS-duplicate-shortcut =
|
zen-settings-CKS-duplicate-shortcut =
|
||||||
.label = Dubliuoti spartųjį klavišą
|
.label = Dubliuoti spartųjį klavišą
|
||||||
zen-settings-CKS-reset-shortcuts =
|
zen-settings-CKS-reset-shortcuts =
|
||||||
.label = Atkurti į numatytuosius
|
.label = Atkurti į numatytuosius nustatymus
|
||||||
zenCKSOption-group-other = Kita
|
zenCKSOption-group-other = Kita
|
||||||
zenCKSOption-group-windowAndTabManagement = Langų ir kortelių tvarkymas
|
zenCKSOption-group-windowAndTabManagement = Langų ir kortelių tvarkymas
|
||||||
zenCKSOption-group-navigation = Naršymas
|
zenCKSOption-group-navigation = Naršymas
|
||||||
@@ -234,7 +234,7 @@ zen-find-shortcut = Rasti puslapyje
|
|||||||
zen-search-find-again-shortcut = Rasti dar kartą
|
zen-search-find-again-shortcut = Rasti dar kartą
|
||||||
zen-search-find-again-shortcut-prev = Rasti ankstesnį
|
zen-search-find-again-shortcut-prev = Rasti ankstesnį
|
||||||
zen-search-find-again-shortcut-2 = Rasti dar kartą (Alt)
|
zen-search-find-again-shortcut-2 = Rasti dar kartą (Alt)
|
||||||
zen-bookmark-this-page-shortcut = Įtraukti šį puslapį į adresyną
|
zen-bookmark-this-page-shortcut = Pridėti šį puslapį prie adresyno
|
||||||
zen-bookmark-show-library-shortcut = Rodyti adresyno biblioteką
|
zen-bookmark-show-library-shortcut = Rodyti adresyno biblioteką
|
||||||
zen-key-stop = Stabdyti įkėlimą
|
zen-key-stop = Stabdyti įkėlimą
|
||||||
zen-full-zoom-reduce-shortcut = Sumažinti
|
zen-full-zoom-reduce-shortcut = Sumažinti
|
||||||
@@ -257,7 +257,7 @@ zen-close-tab-shortcut = Užverti kortelę
|
|||||||
zen-compact-mode-shortcut-show-sidebar = Perjungti slankančią šoninę juostą
|
zen-compact-mode-shortcut-show-sidebar = Perjungti slankančią šoninę juostą
|
||||||
zen-compact-mode-shortcut-show-toolbar = Perjungti slankančią įrankių juostą
|
zen-compact-mode-shortcut-show-toolbar = Perjungti slankančią įrankių juostą
|
||||||
zen-compact-mode-shortcut-toggle = Perjungti kompaktinį režimą
|
zen-compact-mode-shortcut-toggle = Perjungti kompaktinį režimą
|
||||||
zen-glance-expand = Išskleisti spartų pažiūrėjimą
|
zen-glance-expand = Išskleisti greitą pažiūrėjimą
|
||||||
zen-workspace-shortcut-switch-1 = Perjungti į 1 darbo sritį
|
zen-workspace-shortcut-switch-1 = Perjungti į 1 darbo sritį
|
||||||
zen-workspace-shortcut-switch-2 = Perjungti į 2 darbo sritį
|
zen-workspace-shortcut-switch-2 = Perjungti į 2 darbo sritį
|
||||||
zen-workspace-shortcut-switch-3 = Perjungti į 3 darbo sritį
|
zen-workspace-shortcut-switch-3 = Perjungti į 3 darbo sritį
|
||||||
@@ -304,4 +304,4 @@ zen-devtools-toggle-performance-shortcut = Perjungti našumą
|
|||||||
zen-devtools-toggle-storage-shortcut = Perjungti saugyklą
|
zen-devtools-toggle-storage-shortcut = Perjungti saugyklą
|
||||||
zen-devtools-toggle-dom-shortcut = Perjungti DOM
|
zen-devtools-toggle-dom-shortcut = Perjungti DOM
|
||||||
zen-devtools-toggle-accessibility-shortcut = Perjungti prieinamumą
|
zen-devtools-toggle-accessibility-shortcut = Perjungti prieinamumą
|
||||||
zen-close-all-unpinned-tabs-shortcut = Užverti visas neprisegtas korteles
|
zen-close-all-unpinned-tabs-shortcut = Close All Unpinned Tabs
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ pictureinpicture-minimize-btn =
|
|||||||
.tooltip = Sumažinti
|
.tooltip = Sumažinti
|
||||||
zen-panel-ui-gradient-generator-custom-color = Pasirinktinė spalva
|
zen-panel-ui-gradient-generator-custom-color = Pasirinktinė spalva
|
||||||
zen-panel-ui-gradient-generator-saved-message = Gradientas sėkmingai įrašytas.
|
zen-panel-ui-gradient-generator-saved-message = Gradientas sėkmingai įrašytas.
|
||||||
zen-copy-current-url-confirmation = Nukopijuotas dabartinis URL.
|
zen-copy-current-url-confirmation = Copied current URL!
|
||||||
zen-general-cancel-label =
|
zen-general-cancel-label =
|
||||||
.label = Atšaukti
|
.label = Atšaukti
|
||||||
zen-general-confirm =
|
zen-general-confirm =
|
||||||
@@ -59,13 +59,13 @@ urlbar-search-mode-zen_actions = Veiksmai
|
|||||||
zen-site-data-settings = Nustatymai
|
zen-site-data-settings = Nustatymai
|
||||||
zen-generic-manage = Tvarkyti
|
zen-generic-manage = Tvarkyti
|
||||||
zen-generic-more = Daugiau
|
zen-generic-more = Daugiau
|
||||||
zen-generic-next = Sekantis
|
zen-generic-next = Next
|
||||||
# These labels will be used for the site data panel settings
|
# These labels will be used for the site data panel settings
|
||||||
zen-site-data-setting-allow = Leidžiama
|
zen-site-data-setting-allow = Leidžiama
|
||||||
zen-site-data-setting-block = Užblokuota
|
zen-site-data-setting-block = Užblokuota
|
||||||
zen-site-data-protections-enabled = Įjungta
|
zen-site-data-protections-enabled = Enabled
|
||||||
zen-site-data-protections-disabled = Išjungta
|
zen-site-data-protections-disabled = Disabled
|
||||||
zen-site-data-setting-cross-site = Tarpusavio svetainės slapukas
|
zen-site-data-setting-cross-site = Cross-Site cookie
|
||||||
zen-site-data-security-info-extension =
|
zen-site-data-security-info-extension =
|
||||||
.label = Plėtinys
|
.label = Plėtinys
|
||||||
zen-site-data-security-info-secure =
|
zen-site-data-security-info-secure =
|
||||||
@@ -79,16 +79,16 @@ zen-site-data-get-addons =
|
|||||||
zen-site-data-site-settings =
|
zen-site-data-site-settings =
|
||||||
.label = Visi svetainės nustatymai
|
.label = Visi svetainės nustatymai
|
||||||
zen-site-data-header-share =
|
zen-site-data-header-share =
|
||||||
.tooltiptext = Bendrinti šį puslapį
|
.tooltiptext = Share This Page
|
||||||
zen-site-data-header-reader-mode =
|
zen-site-data-header-reader-mode =
|
||||||
.tooltiptext = Įeiti į skaitytojo režimą
|
.tooltiptext = Enter Reader Mode
|
||||||
zen-site-data-header-screenshot =
|
zen-site-data-header-screenshot =
|
||||||
.tooltiptext = Daryti ekrano kopiją
|
.tooltiptext = Take a Screenshot
|
||||||
zen-site-data-header-bookmark =
|
zen-site-data-header-bookmark =
|
||||||
.tooltiptext = Įtraukti šį puslapį į adresyną
|
.tooltiptext = Bookmark This Page
|
||||||
zen-urlbar-copy-url-button =
|
zen-urlbar-copy-url-button =
|
||||||
.tooltiptext = Kopijuoti URL
|
.tooltiptext = Copy URL
|
||||||
zen-site-data-setting-site-protection = Stebėjimo apsauga
|
zen-site-data-setting-site-protection = Tracking Protection
|
||||||
|
|
||||||
# Section: Feature callouts
|
# Section: Feature callouts
|
||||||
|
|
||||||
|
|||||||
@@ -19,5 +19,5 @@ zen-split-view-modifier-header = Skaidymo rodinys
|
|||||||
zen-split-view-modifier-activate-reallocation =
|
zen-split-view-modifier-activate-reallocation =
|
||||||
.label = Aktyvuoti perskyrimą
|
.label = Aktyvuoti perskyrimą
|
||||||
zen-split-view-modifier-enabled-toast = Skaidymo rodinio pertvarkymas įjungtas.
|
zen-split-view-modifier-enabled-toast = Skaidymo rodinio pertvarkymas įjungtas.
|
||||||
zen-split-view-modifier-enabled-toast-description = Nutempkite rodinį, kad pertvarkytumėte. Paspauskite Gr, kad išeitumėte.
|
zen-split-view-modifier-enabled-toast-description = Nutempkite rodinį, kad jį pertvarkytumėte. Paspauskite Gr, kad išeitumėte.
|
||||||
zen-split-view-modifier-disabled-toast = Skaidymo rodinio pertvarkymas išjungtas.
|
zen-split-view-modifier-disabled-toast = Skaidymo rodinio pertvarkymas išjungtas.
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ zen-welcome-workspace-colors-description = Suasmeninkite savo naršyklę, suteik
|
|||||||
zen-welcome-start-browsing-title =
|
zen-welcome-start-browsing-title =
|
||||||
Viskas parengta?<br/>
|
Viskas parengta?<br/>
|
||||||
Pradėkime veikti!
|
Pradėkime veikti!
|
||||||
zen-welcome-start-browsing-description-1 = Viskas parengta ir gali veikti. Spustelėkite žemiau esantį mygtuką, kad pradėtumėte naršyti su „{ -brand-short-name }“.
|
zen-welcome-start-browsing-description-1 = Viskas parengta ir gali veikti. Spustelėkite toliau esantį mygtuką, kad pradėtumėte naršyti su „{ -brand-short-name }“.
|
||||||
zen-welcome-start-browsing = Pirmyn!
|
zen-welcome-start-browsing = Pirmyn!
|
||||||
zen-welcome-default-search-title = Jūsų numatytasis paieškos variklis
|
zen-welcome-default-search-title = Jūsų numatytasis paieškos variklis
|
||||||
zen-welcome-default-search-description = Pasirinkite numatytąjį paieškos variklį. Vėliau visada galite ją pakeisti!
|
zen-welcome-default-search-description = Pasirinkite numatytąjį paieškos variklį. Vėliau visada galite ją pakeisti!
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ zen-workspaces-delete-workspace-title = Ištrinti erdvę?
|
|||||||
zen-workspaces-delete-workspace-body = Ar tikrai norite ištrinti „{ $name }“? Šio veiksmo anuliuoti negalima.
|
zen-workspaces-delete-workspace-body = Ar tikrai norite ištrinti „{ $name }“? Šio veiksmo anuliuoti negalima.
|
||||||
# Note that the html tag MUST not be changed or removed, as it is used to better
|
# Note that the html tag MUST not be changed or removed, as it is used to better
|
||||||
# display the shortcut in the toast notification.
|
# display the shortcut in the toast notification.
|
||||||
zen-workspaces-close-all-unpinned-tabs-toast = Kortelės užvertos! Naudokite <span>{ $shortcut }</span>, kad atšauktumėte.
|
zen-workspaces-close-all-unpinned-tabs-toast = Tabs Closed! Use <span>{ $shortcut }</span> to undo.
|
||||||
zen-workspaces-close-all-unpinned-tabs-title =
|
zen-workspaces-close-all-unpinned-tabs-title =
|
||||||
.label = Valyti
|
.label = Clear
|
||||||
.tooltiptext = Užverti visas neprisegtas korteles
|
.tooltiptext = Close all unpinned tabs
|
||||||
|
|||||||
@@ -304,4 +304,4 @@ zen-devtools-toggle-performance-shortcut = Увімк. / Вимк. продук
|
|||||||
zen-devtools-toggle-storage-shortcut = Увімк. / Вимк. сховище
|
zen-devtools-toggle-storage-shortcut = Увімк. / Вимк. сховище
|
||||||
zen-devtools-toggle-dom-shortcut = Увімк. / Вимк. DOM
|
zen-devtools-toggle-dom-shortcut = Увімк. / Вимк. DOM
|
||||||
zen-devtools-toggle-accessibility-shortcut = Увімк. / Вимк. доступ
|
zen-devtools-toggle-accessibility-shortcut = Увімк. / Вимк. доступ
|
||||||
zen-close-all-unpinned-tabs-shortcut = Закрити всі відкріплені вкладки
|
zen-close-all-unpinned-tabs-shortcut = Close All Unpinned Tabs
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ zen-workspaces-delete-workspace-title = Видалити простір?
|
|||||||
zen-workspaces-delete-workspace-body = Упевнені, що хочете видалити { $name }? Цю дію неможливо скасувати.
|
zen-workspaces-delete-workspace-body = Упевнені, що хочете видалити { $name }? Цю дію неможливо скасувати.
|
||||||
# Note that the html tag MUST not be changed or removed, as it is used to better
|
# Note that the html tag MUST not be changed or removed, as it is used to better
|
||||||
# display the shortcut in the toast notification.
|
# display the shortcut in the toast notification.
|
||||||
zen-workspaces-close-all-unpinned-tabs-toast = Вкладки закрито! Скористайтеся <span>{ $shortcut }</span>, аби повернути їх.
|
zen-workspaces-close-all-unpinned-tabs-toast = Tabs Closed! Use <span>{ $shortcut }</span> to undo.
|
||||||
zen-workspaces-close-all-unpinned-tabs-title =
|
zen-workspaces-close-all-unpinned-tabs-title =
|
||||||
.label = Очистити
|
.label = Clear
|
||||||
.tooltiptext = Закрити всі відкріплені вкладки
|
.tooltiptext = Close all unpinned tabs
|
||||||
|
|||||||
@@ -23,8 +23,7 @@
|
|||||||
value: true
|
value: true
|
||||||
|
|
||||||
- name: media.videocontrols.picture-in-picture.urlbar-button.enabled
|
- name: media.videocontrols.picture-in-picture.urlbar-button.enabled
|
||||||
value: true
|
value: false
|
||||||
locked: true
|
|
||||||
|
|
||||||
# Enable private suggestions
|
# Enable private suggestions
|
||||||
- name: browser.search.suggest.enabled
|
- name: browser.search.suggest.enabled
|
||||||
|
|||||||
@@ -57,6 +57,3 @@
|
|||||||
|
|
||||||
- name: zen.view.shift-down-site-on-hover
|
- name: zen.view.shift-down-site-on-hover
|
||||||
value: false
|
value: false
|
||||||
|
|
||||||
- name: zen.view.show-clear-tabs-button
|
|
||||||
value: true
|
|
||||||
|
|||||||
@@ -26,12 +26,6 @@
|
|||||||
- name: zen.urlbar.enable-overrides
|
- name: zen.urlbar.enable-overrides
|
||||||
value: false
|
value: false
|
||||||
|
|
||||||
- name: zen.urlbar.single-toolbar-show-copy-url
|
|
||||||
value: true
|
|
||||||
|
|
||||||
- name: zen.urlbar.show-pip-button
|
|
||||||
value: false
|
|
||||||
|
|
||||||
# Mark: Zen suggestions controls
|
# Mark: Zen suggestions controls
|
||||||
|
|
||||||
- name: zen.urlbar.suggestions.quick-actions
|
- name: zen.urlbar.suggestions.quick-actions
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
diff --git a/browser/base/content/browser-addons.js b/browser/base/content/browser-addons.js
|
diff --git a/browser/base/content/browser-addons.js b/browser/base/content/browser-addons.js
|
||||||
index 754ce380ed233eb8764af07af3c8dc95d3f39d5c..ed3062bab0b80db3b456cdad03e7efcc31266b08 100644
|
index 754ce380ed233eb8764af07af3c8dc95d3f39d5c..29864ab59819271b7319b273c08bdc2736d40c93 100644
|
||||||
--- a/browser/base/content/browser-addons.js
|
--- a/browser/base/content/browser-addons.js
|
||||||
+++ b/browser/base/content/browser-addons.js
|
+++ b/browser/base/content/browser-addons.js
|
||||||
@@ -1071,7 +1071,7 @@ var gXPInstallObserver = {
|
@@ -1071,7 +1071,7 @@ var gXPInstallObserver = {
|
||||||
@@ -7,7 +7,7 @@ index 754ce380ed233eb8764af07af3c8dc95d3f39d5c..ed3062bab0b80db3b456cdad03e7efcc
|
|||||||
hideClose: true,
|
hideClose: true,
|
||||||
popupOptions: {
|
popupOptions: {
|
||||||
- position: "bottomright topright",
|
- position: "bottomright topright",
|
||||||
+ position: gZenUIManager.panelUIPosition(),
|
+ position: gZenUIManager.panelUIPosition,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ index 754ce380ed233eb8764af07af3c8dc95d3f39d5c..ed3062bab0b80db3b456cdad03e7efcc
|
|||||||
timeout: Date.now() + 30000,
|
timeout: Date.now() + 30000,
|
||||||
popupOptions: {
|
popupOptions: {
|
||||||
- position: "bottomright topright",
|
- position: "bottomright topright",
|
||||||
+ position: gZenUIManager.panelUIPosition(),
|
+ position: gZenUIManager.panelUIPosition,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ index 754ce380ed233eb8764af07af3c8dc95d3f39d5c..ed3062bab0b80db3b456cdad03e7efcc
|
|||||||
this.ensureButtonShownBeforeAttachingPanel(panel);
|
this.ensureButtonShownBeforeAttachingPanel(panel);
|
||||||
PanelMultiView.openPopup(panel, this._button, {
|
PanelMultiView.openPopup(panel, this._button, {
|
||||||
- position: "bottomright topright",
|
- position: "bottomright topright",
|
||||||
+ position: gZenUIManager.panelUIPosition(panel, this._button),
|
+ position: gZenUIManager.panelUIPosition,
|
||||||
triggerEvent: aEvent,
|
triggerEvent: aEvent,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js
|
diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js
|
||||||
index 79b4f6f8fb2f7dd8784920038784e6bb0c967e2d..4db983dad9bea10c17b5ac166ba58b93fa2a4d56 100644
|
index 79b4f6f8fb2f7dd8784920038784e6bb0c967e2d..1f3f4991b3ba7c00516e9708e89e8f95db25a36a 100644
|
||||||
--- a/browser/base/content/browser-places.js
|
--- a/browser/base/content/browser-places.js
|
||||||
+++ b/browser/base/content/browser-places.js
|
+++ b/browser/base/content/browser-places.js
|
||||||
@@ -252,6 +252,8 @@ var StarUI = {
|
@@ -252,6 +252,8 @@ var StarUI = {
|
||||||
@@ -33,11 +33,3 @@ index 79b4f6f8fb2f7dd8784920038784e6bb0c967e2d..4db983dad9bea10c17b5ac166ba58b93
|
|||||||
removeBookmarkButtonCommand: function SU_removeBookmarkButtonCommand() {
|
removeBookmarkButtonCommand: function SU_removeBookmarkButtonCommand() {
|
||||||
this._removeBookmarksOnPopupHidden = true;
|
this._removeBookmarksOnPopupHidden = true;
|
||||||
this.panel.hidePopup();
|
this.panel.hidePopup();
|
||||||
@@ -1800,6 +1817,7 @@ var BookmarkingUI = {
|
|
||||||
document.getElementById("context-bookmarkpage"),
|
|
||||||
PanelMultiView.getViewNode(document, "panelMenuBookmarkThisPage"),
|
|
||||||
document.getElementById("pageAction-panel-bookmark"),
|
|
||||||
+ document.getElementById("zen-site-data-icon-button"),
|
|
||||||
]) {
|
|
||||||
if (!element) {
|
|
||||||
// The page action panel element may not have been created yet.
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
diff --git a/browser/base/content/navigator-toolbox.js b/browser/base/content/navigator-toolbox.js
|
diff --git a/browser/base/content/navigator-toolbox.js b/browser/base/content/navigator-toolbox.js
|
||||||
index 413bad2a62058a1c434d6a44e927e44eb397289d..d28116ffacb0ddb6fdb421db5d6498e455356b4a 100644
|
index 413bad2a62058a1c434d6a44e927e44eb397289d..472eab5d3bca2bc665920707a71105167cbe75ec 100644
|
||||||
--- a/browser/base/content/navigator-toolbox.js
|
--- a/browser/base/content/navigator-toolbox.js
|
||||||
+++ b/browser/base/content/navigator-toolbox.js
|
+++ b/browser/base/content/navigator-toolbox.js
|
||||||
@@ -8,7 +8,7 @@
|
@@ -8,7 +8,7 @@
|
||||||
@@ -11,6 +11,24 @@ index 413bad2a62058a1c434d6a44e927e44eb397289d..d28116ffacb0ddb6fdb421db5d6498e4
|
|||||||
const widgetOverflow = document.getElementById("widget-overflow");
|
const widgetOverflow = document.getElementById("widget-overflow");
|
||||||
|
|
||||||
function onPopupShowing(event) {
|
function onPopupShowing(event) {
|
||||||
|
@@ -110,7 +110,7 @@ document.addEventListener(
|
||||||
|
#pageActionButton,
|
||||||
|
#downloads-button,
|
||||||
|
#fxa-toolbar-menu-button,
|
||||||
|
- #unified-extensions-button,
|
||||||
|
+ #zen-site-data-icon-button,
|
||||||
|
#library-button
|
||||||
|
`);
|
||||||
|
if (!element) {
|
||||||
|
@@ -138,7 +138,7 @@ document.addEventListener(
|
||||||
|
gSync.toggleAccountPanel(element, event);
|
||||||
|
break;
|
||||||
|
|
||||||
|
- case "unified-extensions-button":
|
||||||
|
+ case "zen-site-data-icon-button":
|
||||||
|
gUnifiedExtensions.togglePanel(event);
|
||||||
|
break;
|
||||||
|
|
||||||
@@ -187,6 +187,7 @@ document.addEventListener(
|
@@ -187,6 +187,7 @@ document.addEventListener(
|
||||||
#reload-button ,
|
#reload-button ,
|
||||||
#urlbar-go-button,
|
#urlbar-go-button,
|
||||||
|
|||||||
@@ -48,7 +48,6 @@
|
|||||||
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenFolders.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/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/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/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/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/ZenGradientGenerator.mjs"></script>
|
||||||
@@ -58,3 +57,4 @@
|
|||||||
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenDownloadAnimation.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/ZenEmojiPicker.mjs"></script>
|
||||||
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenWorkspaceCreation.mjs"></script>
|
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenWorkspaceCreation.mjs"></script>
|
||||||
|
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenWindowSyncing.mjs"></script>
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
content/browser/zen-components/ZenWorkspaceIcons.mjs (../../zen/workspaces/ZenWorkspaceIcons.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/ZenWorkspace.mjs (../../zen/workspaces/ZenWorkspace.mjs)
|
||||||
content/browser/zen-components/ZenWorkspaces.mjs (../../zen/workspaces/ZenWorkspaces.mjs)
|
content/browser/zen-components/ZenWorkspaces.mjs (../../zen/workspaces/ZenWorkspaces.mjs)
|
||||||
|
content/browser/zen-components/ZenWindowSyncing.mjs (../../zen/workspaces/ZenWindowSyncing.mjs)
|
||||||
content/browser/zen-components/ZenWorkspaceCreation.mjs (../../zen/workspaces/ZenWorkspaceCreation.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/ZenWorkspacesStorage.mjs (../../zen/workspaces/ZenWorkspacesStorage.mjs)
|
||||||
content/browser/zen-components/ZenWorkspacesSync.mjs (../../zen/workspaces/ZenWorkspacesSync.mjs)
|
content/browser/zen-components/ZenWorkspacesSync.mjs (../../zen/workspaces/ZenWorkspacesSync.mjs)
|
||||||
@@ -50,7 +51,6 @@
|
|||||||
|
|
||||||
content/browser/zen-components/ZenKeyboardShortcuts.mjs (../../zen/kbs/ZenKeyboardShortcuts.mjs)
|
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-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.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-styles/zen-tabs/vertical-tabs.css (../../zen/tabs/zen-tabs/vertical-tabs.css)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
position="bottomright topright">
|
position="bottomright topright">
|
||||||
<panelmultiview mainViewId="unified-extensions-view">
|
<panelmultiview mainViewId="unified-extensions-view">
|
||||||
# We'll keep the view with this name/id in order to prevent
|
# We'll keep the view with this name/id in order to prevent
|
||||||
# any sort of future issues we may have if firefox decides
|
# any sort of future issues we may have if firefox decides
|
||||||
# to change the functionality of this view
|
# to change the functionality of this view
|
||||||
<panelview id="unified-extensions-view"
|
<panelview id="unified-extensions-view"
|
||||||
class="cui-widget-panelview"
|
class="cui-widget-panelview"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
diff --git a/browser/components/customizableui/content/panelUI.js b/browser/components/customizableui/content/panelUI.js
|
diff --git a/browser/components/customizableui/content/panelUI.js b/browser/components/customizableui/content/panelUI.js
|
||||||
index 7156397d597579f745ea20ae2b9327433a31c8ec..23c15c60acd77150ea89bd6f2fa1685a0cfc37fd 100644
|
index 7156397d597579f745ea20ae2b9327433a31c8ec..13b844a63e79e227c96faf153ee5908759306407 100644
|
||||||
--- a/browser/components/customizableui/content/panelUI.js
|
--- a/browser/components/customizableui/content/panelUI.js
|
||||||
+++ b/browser/components/customizableui/content/panelUI.js
|
+++ b/browser/components/customizableui/content/panelUI.js
|
||||||
@@ -518,8 +518,7 @@ const PanelUI = {
|
@@ -518,8 +518,7 @@ const PanelUI = {
|
||||||
@@ -30,7 +30,7 @@ index 7156397d597579f745ea20ae2b9327433a31c8ec..23c15c60acd77150ea89bd6f2fa1685a
|
|||||||
});
|
});
|
||||||
|
|
||||||
- this.notificationPanel.openPopup(anchor, "bottomright topright");
|
- this.notificationPanel.openPopup(anchor, "bottomright topright");
|
||||||
+ this.notificationPanel.openPopup(anchor, gZenUIManager.panelUIPosition(this.notificationPanel, anchor));
|
+ this.notificationPanel.openPopup(anchor, gZenUIManager.panelUIPosition);
|
||||||
},
|
},
|
||||||
|
|
||||||
_clearNotificationPanel() {
|
_clearNotificationPanel() {
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
diff --git a/browser/components/sessionstore/SessionFile.sys.mjs b/browser/components/sessionstore/SessionFile.sys.mjs
|
||||||
|
index 157c55ab24a418b56690d2e26320582909b919e4..14755f57dc450583e69eee94eb11f16980d5e5cb 100644
|
||||||
|
--- a/browser/components/sessionstore/SessionFile.sys.mjs
|
||||||
|
+++ b/browser/components/sessionstore/SessionFile.sys.mjs
|
||||||
|
@@ -22,6 +22,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||||
|
RunState: "resource:///modules/sessionstore/RunState.sys.mjs",
|
||||||
|
SessionStore: "resource:///modules/sessionstore/SessionStore.sys.mjs",
|
||||||
|
SessionWriter: "resource:///modules/sessionstore/SessionWriter.sys.mjs",
|
||||||
|
+ ZenSessionStore: "resource:///modules/zen/ZenSessionManager.sys.mjs",
|
||||||
|
});
|
||||||
|
|
||||||
|
const PREF_UPGRADE_BACKUP = "browser.sessionstore.upgradeBackup.latestBuildID";
|
||||||
|
@@ -364,7 +365,7 @@ var SessionFileInternal = {
|
||||||
|
this._readOrigin = result.origin;
|
||||||
|
|
||||||
|
result.noFilesFound = noFilesFound;
|
||||||
|
-
|
||||||
|
+ await lazy.ZenSessionStore.readFile();
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
diff --git a/browser/components/sessionstore/SessionStartup.sys.mjs b/browser/components/sessionstore/SessionStartup.sys.mjs
|
||||||
|
index be23213ae9ec7e59358a17276c6c3764d38d9996..ca5a8ccc916ceeab5140f1278d15233cefbe5815 100644
|
||||||
|
--- a/browser/components/sessionstore/SessionStartup.sys.mjs
|
||||||
|
+++ b/browser/components/sessionstore/SessionStartup.sys.mjs
|
||||||
|
@@ -40,6 +40,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||||
|
StartupPerformance:
|
||||||
|
"resource:///modules/sessionstore/StartupPerformance.sys.mjs",
|
||||||
|
sessionStoreLogger: "resource:///modules/sessionstore/SessionLogger.sys.mjs",
|
||||||
|
+ ZenSessionStore: "resource:///modules/zen/ZenSessionManager.sys.mjs",
|
||||||
|
});
|
||||||
|
|
||||||
|
const STATE_RUNNING_STR = "running";
|
||||||
|
@@ -179,6 +180,8 @@ export var SessionStartup = {
|
||||||
|
this._initialState = parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ lazy.ZenSessionStore.onFileRead(this._initialState);
|
||||||
|
+
|
||||||
|
if (this._initialState == null) {
|
||||||
|
// No valid session found.
|
||||||
|
this._sessionType = this.NO_SESSION;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
diff --git a/browser/components/sessionstore/SessionStore.sys.mjs b/browser/components/sessionstore/SessionStore.sys.mjs
|
diff --git a/browser/components/sessionstore/SessionStore.sys.mjs b/browser/components/sessionstore/SessionStore.sys.mjs
|
||||||
index eb62ff3e733e43fdaa299babddea3ba0125abb06..8f20ba50b06f5b75d7de08eb4d1b27d89fb95494 100644
|
index eb62ff3e733e43fdaa299babddea3ba0125abb06..6a73ee56c067cba2347a552b4152cd03cda47b6f 100644
|
||||||
--- a/browser/components/sessionstore/SessionStore.sys.mjs
|
--- a/browser/components/sessionstore/SessionStore.sys.mjs
|
||||||
+++ b/browser/components/sessionstore/SessionStore.sys.mjs
|
+++ b/browser/components/sessionstore/SessionStore.sys.mjs
|
||||||
@@ -126,6 +126,8 @@ const TAB_EVENTS = [
|
@@ -126,6 +126,8 @@ const TAB_EVENTS = [
|
||||||
@@ -11,7 +11,15 @@ index eb62ff3e733e43fdaa299babddea3ba0125abb06..8f20ba50b06f5b75d7de08eb4d1b27d8
|
|||||||
];
|
];
|
||||||
|
|
||||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||||
@@ -1904,6 +1906,8 @@ var SessionStoreInternal = {
|
@@ -195,6 +197,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||||
|
TabStateCache: "resource:///modules/sessionstore/TabStateCache.sys.mjs",
|
||||||
|
TabStateFlusher: "resource:///modules/sessionstore/TabStateFlusher.sys.mjs",
|
||||||
|
setTimeout: "resource://gre/modules/Timer.sys.mjs",
|
||||||
|
+ ZenSessionStore: "resource:///modules/zen/ZenSessionManager.sys.mjs",
|
||||||
|
});
|
||||||
|
|
||||||
|
ChromeUtils.defineLazyGetter(lazy, "blankURI", () => {
|
||||||
|
@@ -1904,6 +1907,8 @@ var SessionStoreInternal = {
|
||||||
case "TabPinned":
|
case "TabPinned":
|
||||||
case "TabUnpinned":
|
case "TabUnpinned":
|
||||||
case "SwapDocShells":
|
case "SwapDocShells":
|
||||||
@@ -20,7 +28,7 @@ index eb62ff3e733e43fdaa299babddea3ba0125abb06..8f20ba50b06f5b75d7de08eb4d1b27d8
|
|||||||
this.saveStateDelayed(win);
|
this.saveStateDelayed(win);
|
||||||
break;
|
break;
|
||||||
case "TabGroupCreate":
|
case "TabGroupCreate":
|
||||||
@@ -2139,7 +2143,6 @@ var SessionStoreInternal = {
|
@@ -2139,7 +2144,6 @@ var SessionStoreInternal = {
|
||||||
if (closedWindowState) {
|
if (closedWindowState) {
|
||||||
let newWindowState;
|
let newWindowState;
|
||||||
if (
|
if (
|
||||||
@@ -28,7 +36,18 @@ index eb62ff3e733e43fdaa299babddea3ba0125abb06..8f20ba50b06f5b75d7de08eb4d1b27d8
|
|||||||
!lazy.SessionStartup.willRestore()
|
!lazy.SessionStartup.willRestore()
|
||||||
) {
|
) {
|
||||||
// We want to split the window up into pinned tabs and unpinned tabs.
|
// We want to split the window up into pinned tabs and unpinned tabs.
|
||||||
@@ -2372,11 +2375,9 @@ var SessionStoreInternal = {
|
@@ -2203,6 +2207,10 @@ var SessionStoreInternal = {
|
||||||
|
});
|
||||||
|
this._shouldRestoreLastSession = false;
|
||||||
|
}
|
||||||
|
+ else if (!aInitialState && isRegularWindow) {
|
||||||
|
+ aInitialState = lazy.ZenSessionStore.getNewWindowData(this._windows);
|
||||||
|
+ this.restoreWindows(aWindow, aInitialState, {});
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if (this._restoreLastWindow && aWindow.toolbar.visible) {
|
||||||
|
// always reset (if not a popup window)
|
||||||
|
@@ -2372,11 +2380,9 @@ var SessionStoreInternal = {
|
||||||
tabbrowser.selectedTab.label;
|
tabbrowser.selectedTab.label;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +59,7 @@ index eb62ff3e733e43fdaa299babddea3ba0125abb06..8f20ba50b06f5b75d7de08eb4d1b27d8
|
|||||||
|
|
||||||
// Store the window's close date to figure out when each individual tab
|
// Store the window's close date to figure out when each individual tab
|
||||||
// was closed. This timestamp should allow re-arranging data based on how
|
// was closed. This timestamp should allow re-arranging data based on how
|
||||||
@@ -3361,7 +3362,7 @@ var SessionStoreInternal = {
|
@@ -3361,7 +3367,7 @@ var SessionStoreInternal = {
|
||||||
if (!isPrivateWindow && tabState.isPrivate) {
|
if (!isPrivateWindow && tabState.isPrivate) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -49,7 +68,7 @@ index eb62ff3e733e43fdaa299babddea3ba0125abb06..8f20ba50b06f5b75d7de08eb4d1b27d8
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4073,6 +4074,11 @@ var SessionStoreInternal = {
|
@@ -4073,6 +4079,11 @@ var SessionStoreInternal = {
|
||||||
Math.min(tabState.index, tabState.entries.length)
|
Math.min(tabState.index, tabState.entries.length)
|
||||||
);
|
);
|
||||||
tabState.pinned = false;
|
tabState.pinned = false;
|
||||||
@@ -61,7 +80,7 @@ index eb62ff3e733e43fdaa299babddea3ba0125abb06..8f20ba50b06f5b75d7de08eb4d1b27d8
|
|||||||
|
|
||||||
if (inBackground === false) {
|
if (inBackground === false) {
|
||||||
aWindow.gBrowser.selectedTab = newTab;
|
aWindow.gBrowser.selectedTab = newTab;
|
||||||
@@ -4509,6 +4515,7 @@ var SessionStoreInternal = {
|
@@ -4509,6 +4520,7 @@ var SessionStoreInternal = {
|
||||||
// Append the tab if we're opening into a different window,
|
// Append the tab if we're opening into a different window,
|
||||||
tabIndex: aSource == aTargetWindow ? pos : Infinity,
|
tabIndex: aSource == aTargetWindow ? pos : Infinity,
|
||||||
pinned: state.pinned,
|
pinned: state.pinned,
|
||||||
@@ -69,7 +88,7 @@ index eb62ff3e733e43fdaa299babddea3ba0125abb06..8f20ba50b06f5b75d7de08eb4d1b27d8
|
|||||||
userContextId: state.userContextId,
|
userContextId: state.userContextId,
|
||||||
skipLoad: true,
|
skipLoad: true,
|
||||||
preferredRemoteType,
|
preferredRemoteType,
|
||||||
@@ -5358,7 +5365,7 @@ var SessionStoreInternal = {
|
@@ -5358,7 +5370,7 @@ var SessionStoreInternal = {
|
||||||
|
|
||||||
for (let i = tabbrowser.pinnedTabCount; i < tabbrowser.tabs.length; i++) {
|
for (let i = tabbrowser.pinnedTabCount; i < tabbrowser.tabs.length; i++) {
|
||||||
let tab = tabbrowser.tabs[i];
|
let tab = tabbrowser.tabs[i];
|
||||||
@@ -78,7 +97,7 @@ index eb62ff3e733e43fdaa299babddea3ba0125abb06..8f20ba50b06f5b75d7de08eb4d1b27d8
|
|||||||
removableTabs.push(tab);
|
removableTabs.push(tab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5418,7 +5425,7 @@ var SessionStoreInternal = {
|
@@ -5418,7 +5430,7 @@ var SessionStoreInternal = {
|
||||||
}
|
}
|
||||||
|
|
||||||
let workspaceID = aWindow.getWorkspaceID();
|
let workspaceID = aWindow.getWorkspaceID();
|
||||||
@@ -87,7 +106,7 @@ index eb62ff3e733e43fdaa299babddea3ba0125abb06..8f20ba50b06f5b75d7de08eb4d1b27d8
|
|||||||
winData.workspaceID = workspaceID;
|
winData.workspaceID = workspaceID;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -5609,11 +5616,12 @@ var SessionStoreInternal = {
|
@@ -5609,11 +5621,12 @@ var SessionStoreInternal = {
|
||||||
}
|
}
|
||||||
|
|
||||||
let tabbrowser = aWindow.gBrowser;
|
let tabbrowser = aWindow.gBrowser;
|
||||||
@@ -101,7 +120,7 @@ index eb62ff3e733e43fdaa299babddea3ba0125abb06..8f20ba50b06f5b75d7de08eb4d1b27d8
|
|||||||
// update the internal state data for this window
|
// update the internal state data for this window
|
||||||
for (let tab of tabs) {
|
for (let tab of tabs) {
|
||||||
if (tab == aWindow.FirefoxViewHandler.tab) {
|
if (tab == aWindow.FirefoxViewHandler.tab) {
|
||||||
@@ -5624,6 +5632,7 @@ var SessionStoreInternal = {
|
@@ -5624,6 +5637,7 @@ var SessionStoreInternal = {
|
||||||
tabsData.push(tabData);
|
tabsData.push(tabData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +128,7 @@ index eb62ff3e733e43fdaa299babddea3ba0125abb06..8f20ba50b06f5b75d7de08eb4d1b27d8
|
|||||||
// update tab group state for this window
|
// update tab group state for this window
|
||||||
winData.groups = [];
|
winData.groups = [];
|
||||||
for (let tabGroup of aWindow.gBrowser.tabGroups) {
|
for (let tabGroup of aWindow.gBrowser.tabGroups) {
|
||||||
@@ -5636,7 +5645,7 @@ var SessionStoreInternal = {
|
@@ -5636,7 +5650,7 @@ var SessionStoreInternal = {
|
||||||
// a window is closed, point to the first item in the tab strip instead (it will never be the Firefox View tab,
|
// a window is closed, point to the first item in the tab strip instead (it will never be the Firefox View tab,
|
||||||
// since it's only inserted into the tab strip after it's selected).
|
// since it's only inserted into the tab strip after it's selected).
|
||||||
if (aWindow.FirefoxViewHandler.tab?.selected) {
|
if (aWindow.FirefoxViewHandler.tab?.selected) {
|
||||||
@@ -118,7 +137,7 @@ index eb62ff3e733e43fdaa299babddea3ba0125abb06..8f20ba50b06f5b75d7de08eb4d1b27d8
|
|||||||
winData.title = tabbrowser.tabs[0].label;
|
winData.title = tabbrowser.tabs[0].label;
|
||||||
}
|
}
|
||||||
winData.selected = selectedIndex;
|
winData.selected = selectedIndex;
|
||||||
@@ -5748,8 +5757,8 @@ var SessionStoreInternal = {
|
@@ -5748,8 +5762,8 @@ var SessionStoreInternal = {
|
||||||
// selectTab represents.
|
// selectTab represents.
|
||||||
let selectTab = 0;
|
let selectTab = 0;
|
||||||
if (overwriteTabs) {
|
if (overwriteTabs) {
|
||||||
@@ -129,7 +148,7 @@ index eb62ff3e733e43fdaa299babddea3ba0125abb06..8f20ba50b06f5b75d7de08eb4d1b27d8
|
|||||||
selectTab = Math.min(selectTab, winData.tabs.length);
|
selectTab = Math.min(selectTab, winData.tabs.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5792,6 +5801,8 @@ var SessionStoreInternal = {
|
@@ -5792,6 +5806,8 @@ var SessionStoreInternal = {
|
||||||
winData.tabs,
|
winData.tabs,
|
||||||
winData.groups ?? []
|
winData.groups ?? []
|
||||||
);
|
);
|
||||||
@@ -138,7 +157,7 @@ index eb62ff3e733e43fdaa299babddea3ba0125abb06..8f20ba50b06f5b75d7de08eb4d1b27d8
|
|||||||
this._log.debug(
|
this._log.debug(
|
||||||
`restoreWindow, createTabsForSessionRestore returned ${tabs.length} tabs`
|
`restoreWindow, createTabsForSessionRestore returned ${tabs.length} tabs`
|
||||||
);
|
);
|
||||||
@@ -6348,6 +6359,25 @@ var SessionStoreInternal = {
|
@@ -6348,6 +6364,25 @@ var SessionStoreInternal = {
|
||||||
|
|
||||||
// Most of tabData has been restored, now continue with restoring
|
// Most of tabData has been restored, now continue with restoring
|
||||||
// attributes that may trigger external events.
|
// attributes that may trigger external events.
|
||||||
@@ -152,8 +171,8 @@ index eb62ff3e733e43fdaa299babddea3ba0125abb06..8f20ba50b06f5b75d7de08eb4d1b27d8
|
|||||||
+ if (tabData.zenHasStaticLabel) {
|
+ if (tabData.zenHasStaticLabel) {
|
||||||
+ tab.setAttribute("zen-has-static-label", "true");
|
+ tab.setAttribute("zen-has-static-label", "true");
|
||||||
+ }
|
+ }
|
||||||
+ if (tabData.zenPinnedId) {
|
+ if (tabData.zenSyncId) {
|
||||||
+ tab.setAttribute("zen-pin-id", tabData.zenPinnedId);
|
+ tab.setAttribute("zen-sync-id", tabData.zenSyncId);
|
||||||
+ }
|
+ }
|
||||||
+ if (tabData.zenDefaultUserContextId) {
|
+ if (tabData.zenDefaultUserContextId) {
|
||||||
+ tab.setAttribute("zenDefaultUserContextId", true);
|
+ tab.setAttribute("zenDefaultUserContextId", true);
|
||||||
@@ -164,7 +183,7 @@ index eb62ff3e733e43fdaa299babddea3ba0125abb06..8f20ba50b06f5b75d7de08eb4d1b27d8
|
|||||||
|
|
||||||
if (tabData.pinned) {
|
if (tabData.pinned) {
|
||||||
tabbrowser.pinTab(tab);
|
tabbrowser.pinTab(tab);
|
||||||
@@ -7263,7 +7293,7 @@ var SessionStoreInternal = {
|
@@ -7263,7 +7298,7 @@ var SessionStoreInternal = {
|
||||||
|
|
||||||
let groupsToSave = new Map();
|
let groupsToSave = new Map();
|
||||||
for (let tIndex = 0; tIndex < window.tabs.length; ) {
|
for (let tIndex = 0; tIndex < window.tabs.length; ) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
diff --git a/browser/components/sessionstore/TabState.sys.mjs b/browser/components/sessionstore/TabState.sys.mjs
|
diff --git a/browser/components/sessionstore/TabState.sys.mjs b/browser/components/sessionstore/TabState.sys.mjs
|
||||||
index 82721356d191055bec0d4b0ca49e481221988801..1ea5c394c704da295149443d7794961a12f2060b 100644
|
index 82721356d191055bec0d4b0ca49e481221988801..d1323fe17c995611ebdfe2869b0ccd2d45bcfa11 100644
|
||||||
--- a/browser/components/sessionstore/TabState.sys.mjs
|
--- a/browser/components/sessionstore/TabState.sys.mjs
|
||||||
+++ b/browser/components/sessionstore/TabState.sys.mjs
|
+++ b/browser/components/sessionstore/TabState.sys.mjs
|
||||||
@@ -85,7 +85,22 @@ class _TabState {
|
@@ -85,7 +85,22 @@ class _TabState {
|
||||||
@@ -7,7 +7,7 @@ index 82721356d191055bec0d4b0ca49e481221988801..1ea5c394c704da295149443d7794961a
|
|||||||
}
|
}
|
||||||
|
|
||||||
+ tabData.zenWorkspace = tab.getAttribute("zen-workspace-id");
|
+ tabData.zenWorkspace = tab.getAttribute("zen-workspace-id");
|
||||||
+ tabData.zenPinnedId = tab.getAttribute("zen-pin-id");
|
+ tabData.zenSyncId = tab.getAttribute("zen-sync-id");
|
||||||
+ tabData.zenEssential = tab.getAttribute("zen-essential");
|
+ tabData.zenEssential = tab.getAttribute("zen-essential");
|
||||||
+ tabData.pinned = tabData.pinned || tabData.zenEssential;
|
+ tabData.pinned = tabData.pinned || tabData.zenEssential;
|
||||||
+ tabData.zenDefaultUserContextId = tab.getAttribute("zenDefaultUserContextId");
|
+ tabData.zenDefaultUserContextId = tab.getAttribute("zenDefaultUserContextId");
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
diff --git a/browser/components/tabbrowser/AsyncTabSwitcher.sys.mjs b/browser/components/tabbrowser/AsyncTabSwitcher.sys.mjs
|
diff --git a/browser/components/tabbrowser/AsyncTabSwitcher.sys.mjs b/browser/components/tabbrowser/AsyncTabSwitcher.sys.mjs
|
||||||
index 773f595e89e268578ba153907babec95b58a155a..7cb99cde00c19f50fd9aa48ab1efcfaeaef89771 100644
|
index 773f595e89e268578ba153907babec95b58a155a..abe86fc3d243a85c4a8dbee854a2d0130f7270fd 100644
|
||||||
--- a/browser/components/tabbrowser/AsyncTabSwitcher.sys.mjs
|
--- a/browser/components/tabbrowser/AsyncTabSwitcher.sys.mjs
|
||||||
+++ b/browser/components/tabbrowser/AsyncTabSwitcher.sys.mjs
|
+++ b/browser/components/tabbrowser/AsyncTabSwitcher.sys.mjs
|
||||||
@@ -937,6 +937,7 @@ export class AsyncTabSwitcher {
|
@@ -937,6 +937,7 @@ export class AsyncTabSwitcher {
|
||||||
return !(
|
return !(
|
||||||
this.tabbrowser._printPreviewBrowsers.has(browser) ||
|
this.tabbrowser._printPreviewBrowsers.has(browser) ||
|
||||||
lazy.PictureInPicture.isOriginatingBrowser(browser)
|
lazy.PictureInPicture.isOriginatingBrowser(browser)
|
||||||
+ || browser?.parentNode?.parentNode?.parentNode?.classList?.contains("zen-glance-background")
|
+ || browser?.hasAttribute('zen-glance-background')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -121,14 +121,6 @@ index 425aaf8c8e4adf1507eb0d8ded671f8295544b04..12988986c4cf00990c1d1b2e4be362ef
|
|||||||
on_click(event) {
|
on_click(event) {
|
||||||
if (event.button != 0) {
|
if (event.button != 0) {
|
||||||
return;
|
return;
|
||||||
@@ -570,6 +592,7 @@
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
+ gZenPinnedTabManager._removePinnedAttributes(this, true);
|
|
||||||
gBrowser.removeTab(this, {
|
|
||||||
animate: true,
|
|
||||||
triggeringEvent: event,
|
|
||||||
@@ -582,6 +605,14 @@
|
@@ -582,6 +605,14 @@
|
||||||
// (see tabbrowser-tabs 'click' handler).
|
// (see tabbrowser-tabs 'click' handler).
|
||||||
gBrowser.tabContainer._blockDblClick = true;
|
gBrowser.tabContainer._blockDblClick = true;
|
||||||
|
|||||||
@@ -477,16 +477,6 @@ index c099e8646b9341a3ff55bf394037c8fc2769969b..0d524a0519bbbdf304a594d1fb56c394
|
|||||||
|
|
||||||
TabBarVisibility.update();
|
TabBarVisibility.update();
|
||||||
}
|
}
|
||||||
@@ -4553,6 +4680,9 @@
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ for (let tab of selectedTabs) {
|
|
||||||
+ gZenPinnedTabManager._removePinnedAttributes(tab, true);
|
|
||||||
+ }
|
|
||||||
this.removeTabs(selectedTabs, { isUserTriggered, telemetrySource });
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -4814,6 +4944,7 @@
|
@@ -4814,6 +4944,7 @@
|
||||||
telemetrySource,
|
telemetrySource,
|
||||||
} = {}
|
} = {}
|
||||||
@@ -838,11 +828,3 @@ index c099e8646b9341a3ff55bf394037c8fc2769969b..0d524a0519bbbdf304a594d1fb56c394
|
|||||||
// Build Ask Chat items
|
// Build Ask Chat items
|
||||||
TabContextMenu.GenAI.buildTabMenu(
|
TabContextMenu.GenAI.buildTabMenu(
|
||||||
document.getElementById("context_askChat"),
|
document.getElementById("context_askChat"),
|
||||||
@@ -9763,6 +9944,7 @@ var TabContextMenu = {
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
+ gZenPinnedTabManager._removePinnedAttributes(this.contextTab, true);
|
|
||||||
gBrowser.removeTab(this.contextTab, {
|
|
||||||
animate: true,
|
|
||||||
...gBrowser.TabMetrics.userTriggeredContext(
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
diff --git a/browser/modules/ExtensionsUI.sys.mjs b/browser/modules/ExtensionsUI.sys.mjs
|
diff --git a/browser/modules/ExtensionsUI.sys.mjs b/browser/modules/ExtensionsUI.sys.mjs
|
||||||
index 17cad7b3fbdd6dff862483892f37f72c00792c88..90ea4d95738eb50d1a4a67ee7df087e7c2a68b3d 100644
|
index 17cad7b3fbdd6dff862483892f37f72c00792c88..72d87d70182abfbf664b1dc86f4b4a3ecb2b1d01 100644
|
||||||
--- a/browser/modules/ExtensionsUI.sys.mjs
|
--- a/browser/modules/ExtensionsUI.sys.mjs
|
||||||
+++ b/browser/modules/ExtensionsUI.sys.mjs
|
+++ b/browser/modules/ExtensionsUI.sys.mjs
|
||||||
@@ -478,7 +478,7 @@ export var ExtensionsUI = {
|
@@ -478,7 +478,7 @@ export var ExtensionsUI = {
|
||||||
@@ -7,7 +7,7 @@ index 17cad7b3fbdd6dff862483892f37f72c00792c88..90ea4d95738eb50d1a4a67ee7df087e7
|
|||||||
removeOnDismissal: true,
|
removeOnDismissal: true,
|
||||||
popupOptions: {
|
popupOptions: {
|
||||||
- position: "bottomright topright",
|
- position: "bottomright topright",
|
||||||
+ position: window.gZenUIManager.panelUIPosition(),
|
+ position: window.gZenUIManager.panelUIPosition,
|
||||||
},
|
},
|
||||||
// Pass additional options used internally by the
|
// Pass additional options used internally by the
|
||||||
// addon-webext-permissions-notification custom element
|
// addon-webext-permissions-notification custom element
|
||||||
|
|||||||
@@ -399,10 +399,6 @@
|
|||||||
&:not([can-close='true']) .toolbarbutton-icon {
|
&:not([can-close='true']) .toolbarbutton-icon {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media -moz-pref('zen.view.show-clear-tabs-button', false) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.zen-workspace-actions-reorder-icon,
|
.zen-workspace-actions-reorder-icon,
|
||||||
@@ -517,7 +513,7 @@
|
|||||||
-moz-context-properties: fill, fill-opacity;
|
-moz-context-properties: fill, fill-opacity;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
&:is([open], [starred]) image {
|
&[open] image {
|
||||||
list-style-image: url('permissions-fill.svg');
|
list-style-image: url('permissions-fill.svg');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,3 +13,4 @@
|
|||||||
category app-startup nsBrowserGlue @mozilla.org/browser/browserglue;1 application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
|
category app-startup nsBrowserGlue @mozilla.org/browser/browserglue;1 application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
|
||||||
|
|
||||||
#include common/Components.manifest
|
#include common/Components.manifest
|
||||||
|
#include sessionstore/SessionComponents.manifest
|
||||||
|
|||||||
@@ -42,9 +42,6 @@ let JSWINDOWACTORS = {
|
|||||||
esModuleURI: 'resource:///actors/ZenGlanceChild.sys.mjs',
|
esModuleURI: 'resource:///actors/ZenGlanceChild.sys.mjs',
|
||||||
events: {
|
events: {
|
||||||
DOMContentLoaded: {},
|
DOMContentLoaded: {},
|
||||||
click: {
|
|
||||||
capture: true,
|
|
||||||
},
|
|
||||||
keydown: {
|
keydown: {
|
||||||
capture: true,
|
capture: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
if (tabData.zenWorkspace) {
|
if (tabData.zenWorkspace) {
|
||||||
tab.setAttribute('zen-workspace-id', tabData.zenWorkspace);
|
tab.setAttribute('zen-workspace-id', tabData.zenWorkspace);
|
||||||
}
|
}
|
||||||
if (tabData.zenPinnedId) {
|
if (tabData.zenSyncId) {
|
||||||
tab.setAttribute('zen-pin-id', tabData.zenPinnedId);
|
tab.setAttribute('zen-sync-id', tabData.zenSyncId);
|
||||||
}
|
}
|
||||||
if (tabData.zenHasStaticLabel) {
|
if (tabData.zenHasStaticLabel) {
|
||||||
tab.setAttribute('zen-has-static-label', 'true');
|
tab.setAttribute('zen-has-static-label', 'true');
|
||||||
|
|||||||
@@ -610,60 +610,10 @@ var gZenUIManager = {
|
|||||||
this._toastTimeouts[messageId] = setTimeout(timeoutFunction, options.timeout || 2000);
|
this._toastTimeouts[messageId] = setTimeout(timeoutFunction, options.timeout || 2000);
|
||||||
},
|
},
|
||||||
|
|
||||||
panelUIPosition(panel, anchor) {
|
get panelUIPosition() {
|
||||||
void panel;
|
return gZenVerticalTabsManager._hasSetSingleToolbar && !gZenVerticalTabsManager._prefsRightSide
|
||||||
// The alignment position of the panel is determined during the "popuppositioned" event
|
? 'bottomleft topleft'
|
||||||
// when the panel opens. The alignment positions help us determine in which orientation
|
: 'bottomright topright';
|
||||||
// the panel is anchored to the screen space.
|
|
||||||
//
|
|
||||||
// * "after_start": The panel is anchored at the top-left corner in LTR locales, top-right in RTL locales.
|
|
||||||
// * "after_end": The panel is anchored at the top-right corner in LTR locales, top-left in RTL locales.
|
|
||||||
// * "before_start": The panel is anchored at the bottom-left corner in LTR locales, bottom-right in RTL locales.
|
|
||||||
// * "before_end": The panel is anchored at the bottom-right corner in LTR locales, bottom-left in RTL locales.
|
|
||||||
//
|
|
||||||
// ┌─Anchor(LTR) ┌─Anchor(RTL)
|
|
||||||
// │ Anchor(RTL)─┐ │ Anchor(LTR)─┐
|
|
||||||
// │ │ │ │
|
|
||||||
// x───────────────────x x───────────────────x
|
|
||||||
// │ │ │ │
|
|
||||||
// │ Panel │ │ Panel │
|
|
||||||
// │ "after_start" │ │ "after_end" │
|
|
||||||
// │ │ │ │
|
|
||||||
// └───────────────────┘ └───────────────────┘
|
|
||||||
//
|
|
||||||
// ┌───────────────────┐ ┌───────────────────┐
|
|
||||||
// │ │ │ │
|
|
||||||
// │ Panel │ │ Panel │
|
|
||||||
// │ "before_start" │ │ "before_end" │
|
|
||||||
// │ │ │ │
|
|
||||||
// x───────────────────x x───────────────────x
|
|
||||||
// │ │ │ │
|
|
||||||
// │ Anchor(RTL)─┘ │ Anchor(LTR)─┘
|
|
||||||
// └─Anchor(LTR) └─Anchor(RTL)
|
|
||||||
//
|
|
||||||
// The default choice for the panel is "after_start", to match the content context menu's alignment. However, it is
|
|
||||||
// possible to end up with any of the four combinations. Before the panel is opened, the XUL popup manager needs to
|
|
||||||
// make a determination about the size of the panel and whether or not it will fit within the visible screen area with
|
|
||||||
// the intended alignment. The manager may change the panel's alignment before opening to ensure the panel is fully visible.
|
|
||||||
//
|
|
||||||
// For example, if the panel is opened such that the bottom edge would be rendered off screen, then the XUL popup manager
|
|
||||||
// will change the alignment from "after_start" to "before_start", anchoring the panel's bottom corner to the target screen
|
|
||||||
// location instead of its top corner. This transformation ensures that the whole of the panel is visible on the screen.
|
|
||||||
//
|
|
||||||
// When the panel is anchored by one of its bottom corners (the "before_..." options), then it causes unintentionally odd
|
|
||||||
// behavior where dragging the text-area resizer downward with the mouse actually grows the panel's top edge upward, since
|
|
||||||
// the bottom of the panel is anchored in place. We want to disable the resizer if the panel was positioned to be anchored
|
|
||||||
// from one of its bottom corners.
|
|
||||||
let block = 'bottomleft';
|
|
||||||
let inline = 'topleft';
|
|
||||||
if (anchor?.closest('#zen-sidebar-top-buttons')) {
|
|
||||||
block = 'topleft';
|
|
||||||
}
|
|
||||||
if (gZenVerticalTabsManager._hasSetSingleToolbar && !gZenVerticalTabsManager._prefsRightSide) {
|
|
||||||
block = 'bottomright';
|
|
||||||
inline = 'topright';
|
|
||||||
}
|
|
||||||
return `${block} ${inline}`;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
urlStringsDomainMatch(url1, url2) {
|
urlStringsDomainMatch(url1, url2) {
|
||||||
@@ -1299,14 +1249,6 @@ var gZenVerticalTabsManager = {
|
|||||||
} else {
|
} else {
|
||||||
gBrowser.setTabTitle(this._tabEdited);
|
gBrowser.setTabTitle(this._tabEdited);
|
||||||
}
|
}
|
||||||
if (this._tabEdited.getAttribute('zen-pin-id')) {
|
|
||||||
// Update pin title in storage
|
|
||||||
await gZenPinnedTabManager.updatePinTitle(
|
|
||||||
this._tabEdited,
|
|
||||||
this._tabEdited.label,
|
|
||||||
!!newName
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Maybe add some confetti here?!?
|
// Maybe add some confetti here?!?
|
||||||
gZenUIManager.motion.animate(
|
gZenUIManager.motion.animate(
|
||||||
|
|||||||
@@ -189,18 +189,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media -moz-pref('zen.urlbar.single-toolbar-show-copy-url', false) {
|
|
||||||
:root[zen-single-toolbar='true'] #zen-copy-url-button {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media not -moz-pref('zen.urlbar.show-pip-button') {
|
|
||||||
#picture-in-picture-button {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.urlbar-page-action,
|
.urlbar-page-action,
|
||||||
#tracking-protection-icon-container {
|
#tracking-protection-icon-container {
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
|
|||||||
@@ -500,7 +500,7 @@ body > #confetti {
|
|||||||
#zen-site-data-header {
|
#zen-site-data-header {
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 10px 9px;
|
padding: 8px;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
|
|
||||||
:root[zen-single-toolbar='true']:not([zen-right-side='true']) & {
|
:root[zen-single-toolbar='true']:not([zen-right-side='true']) & {
|
||||||
@@ -609,10 +609,3 @@ body > #confetti {
|
|||||||
#widget-overflow-list {
|
#widget-overflow-list {
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Contextual new tab popup menu */
|
|
||||||
#navigator-toolbox #titlebar #TabsToolbar #tabs-newtab-button > .new-tab-popup > menuitem {
|
|
||||||
& > :is(.menu-highlightable-text, .menu-accel) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -42,7 +42,6 @@
|
|||||||
|
|
||||||
:root[zen-no-padding='true'] & {
|
:root[zen-no-padding='true'] & {
|
||||||
--zen-compact-float: 10px;
|
--zen-compact-float: 10px;
|
||||||
--zen-compact-top-toolbar-hidden-fix: var(--zen-compact-float);
|
|
||||||
--zen-compact-mode-no-padding-radius-fix: 2px;
|
--zen-compact-mode-no-padding-radius-fix: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +68,7 @@
|
|||||||
bottom: calc(var(--zen-compact-float) / 2);
|
bottom: calc(var(--zen-compact-float) / 2);
|
||||||
height: calc(100% - var(--zen-toolbar-height-with-bookmarks));
|
height: calc(100% - var(--zen-toolbar-height-with-bookmarks));
|
||||||
@media -moz-pref('zen.view.compact.hide-toolbar') {
|
@media -moz-pref('zen.view.compact.hide-toolbar') {
|
||||||
height: calc(100% - var(--zen-compact-top-toolbar-hidden-fix, 0px));
|
height: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
& #zen-sidebar-top-buttons {
|
& #zen-sidebar-top-buttons {
|
||||||
|
|||||||
@@ -150,7 +150,6 @@
|
|||||||
for (let tab of this.allItems.reverse()) {
|
for (let tab of this.allItems.reverse()) {
|
||||||
tab = tab.group.hasAttribute('split-view-group') ? tab.group : tab;
|
tab = tab.group.hasAttribute('split-view-group') ? tab.group : tab;
|
||||||
if (tab.hasAttribute('zen-empty-tab')) {
|
if (tab.hasAttribute('zen-empty-tab')) {
|
||||||
await ZenPinnedTabsStorage.removePin(tab.getAttribute('zen-pin-id'));
|
|
||||||
gBrowser.removeTab(tab);
|
gBrowser.removeTab(tab);
|
||||||
} else {
|
} else {
|
||||||
gBrowser.ungroupTab(tab);
|
gBrowser.ungroupTab(tab);
|
||||||
@@ -160,7 +159,6 @@
|
|||||||
|
|
||||||
async delete() {
|
async delete() {
|
||||||
for (const tab of this.allItemsRecursive) {
|
for (const tab of this.allItemsRecursive) {
|
||||||
await ZenPinnedTabsStorage.removePin(tab.getAttribute('zen-pin-id'));
|
|
||||||
if (tab.hasAttribute('zen-empty-tab')) {
|
if (tab.hasAttribute('zen-empty-tab')) {
|
||||||
// Manually remove the empty tabs as removeTabs() inside removeTabGroup
|
// Manually remove the empty tabs as removeTabs() inside removeTabGroup
|
||||||
// does ignore them.
|
// does ignore them.
|
||||||
|
|||||||
@@ -508,9 +508,6 @@
|
|||||||
tabs = [emptyTab, ...filteredTabs];
|
tabs = [emptyTab, ...filteredTabs];
|
||||||
|
|
||||||
const folder = this._createFolderNode(options);
|
const folder = this._createFolderNode(options);
|
||||||
if (options.initialPinId) {
|
|
||||||
folder.setAttribute('zen-pin-id', options.initialPinId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.insertAfter) {
|
if (options.insertAfter) {
|
||||||
options.insertAfter.after(folder);
|
options.insertAfter.after(folder);
|
||||||
@@ -940,7 +937,7 @@
|
|||||||
if (!parentFolder && folder.hasAttribute('split-view-group')) continue;
|
if (!parentFolder && folder.hasAttribute('split-view-group')) continue;
|
||||||
const emptyFolderTabs = folder.tabs
|
const emptyFolderTabs = folder.tabs
|
||||||
.filter((tab) => tab.hasAttribute('zen-empty-tab'))
|
.filter((tab) => tab.hasAttribute('zen-empty-tab'))
|
||||||
.map((tab) => tab.getAttribute('zen-pin-id'));
|
.map((tab) => tab.getAttribute('zen-sync-id'));
|
||||||
|
|
||||||
let prevSiblingInfo = null;
|
let prevSiblingInfo = null;
|
||||||
const prevSibling = folder.previousElementSibling;
|
const prevSibling = folder.previousElementSibling;
|
||||||
@@ -949,8 +946,8 @@
|
|||||||
if (prevSibling) {
|
if (prevSibling) {
|
||||||
if (gBrowser.isTabGroup(prevSibling)) {
|
if (gBrowser.isTabGroup(prevSibling)) {
|
||||||
prevSiblingInfo = { type: 'group', id: prevSibling.id };
|
prevSiblingInfo = { type: 'group', id: prevSibling.id };
|
||||||
} else if (gBrowser.isTab(prevSibling) && prevSibling.hasAttribute('zen-pin-id')) {
|
} else if (gBrowser.isTab(prevSibling) && prevSibling.hasAttribute('zen-sync-id')) {
|
||||||
const zenPinId = prevSibling.getAttribute('zen-pin-id');
|
const zenPinId = prevSibling.getAttribute('zen-sync-id');
|
||||||
prevSiblingInfo = { type: 'tab', id: zenPinId };
|
prevSiblingInfo = { type: 'tab', id: zenPinId };
|
||||||
} else {
|
} else {
|
||||||
prevSiblingInfo = { type: 'start', id: null };
|
prevSiblingInfo = { type: 'start', id: null };
|
||||||
@@ -969,7 +966,7 @@
|
|||||||
prevSiblingInfo: prevSiblingInfo,
|
prevSiblingInfo: prevSiblingInfo,
|
||||||
emptyTabIds: emptyFolderTabs,
|
emptyTabIds: emptyFolderTabs,
|
||||||
userIcon: userIcon?.getAttribute('href'),
|
userIcon: userIcon?.getAttribute('href'),
|
||||||
pinId: folder.getAttribute('zen-pin-id'),
|
syncId: folder.getAttribute('zen-sync-id'),
|
||||||
// note: We shouldn't be using the workspace-id anywhere, we are just
|
// note: We shouldn't be using the workspace-id anywhere, we are just
|
||||||
// remembering it for the pinned tabs manager to use it later.
|
// remembering it for the pinned tabs manager to use it later.
|
||||||
workspaceId: folder.getAttribute('zen-workspace-id'),
|
workspaceId: folder.getAttribute('zen-workspace-id'),
|
||||||
@@ -996,9 +993,9 @@
|
|||||||
tabFolderWorkingData.set(folderData.id, workingData);
|
tabFolderWorkingData.set(folderData.id, workingData);
|
||||||
|
|
||||||
const oldGroup = document.getElementById(folderData.id);
|
const oldGroup = document.getElementById(folderData.id);
|
||||||
folderData.emptyTabIds.forEach((zenPinId) => {
|
folderData.emptyTabIds.forEach((zenSyncId) => {
|
||||||
oldGroup
|
oldGroup
|
||||||
?.querySelector(`tab[zen-pin-id="${zenPinId}"]`)
|
?.querySelector(`tab[zen-sync-id="${zenSyncId}"]`)
|
||||||
?.setAttribute('zen-empty-tab', true);
|
?.setAttribute('zen-empty-tab', true);
|
||||||
});
|
});
|
||||||
if (oldGroup) {
|
if (oldGroup) {
|
||||||
@@ -1011,7 +1008,7 @@
|
|||||||
saveOnWindowClose: folderData.saveOnWindowClose,
|
saveOnWindowClose: folderData.saveOnWindowClose,
|
||||||
workspaceId: folderData.workspaceId,
|
workspaceId: folderData.workspaceId,
|
||||||
});
|
});
|
||||||
folder.setAttribute('zen-pin-id', folderData.pinId);
|
folder.setAttribute('zen-sync-id', folderData.syncId);
|
||||||
workingData.node = folder;
|
workingData.node = folder;
|
||||||
oldGroup.before(folder);
|
oldGroup.before(folder);
|
||||||
} else {
|
} else {
|
||||||
@@ -1044,7 +1041,7 @@
|
|||||||
switch (stateData?.prevSiblingInfo?.type) {
|
switch (stateData?.prevSiblingInfo?.type) {
|
||||||
case 'tab': {
|
case 'tab': {
|
||||||
const tab = parentWorkingData.node.querySelector(
|
const tab = parentWorkingData.node.querySelector(
|
||||||
`[zen-pin-id="${stateData.prevSiblingInfo.id}"]`
|
`[zen-sync-id="${stateData.prevSiblingInfo.id}"]`
|
||||||
);
|
);
|
||||||
tab.after(node);
|
tab.after(node);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -844,10 +844,6 @@
|
|||||||
* @returns {Promise} Promise that resolves when closing is complete
|
* @returns {Promise} Promise that resolves when closing is complete
|
||||||
*/
|
*/
|
||||||
#animateGlanceClosing(onTabClose, browserSidebarContainer, sidebarButtons, setNewID) {
|
#animateGlanceClosing(onTabClose, browserSidebarContainer, sidebarButtons, setNewID) {
|
||||||
if (this.closingGlance) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.closingGlance = true;
|
this.closingGlance = true;
|
||||||
this._animating = true;
|
this._animating = true;
|
||||||
|
|
||||||
@@ -926,7 +922,7 @@
|
|||||||
opacity: [0.4, 1],
|
opacity: [0.4, 1],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
duration: this.#GLANCE_ANIMATION_DURATION / 1.5,
|
duration: this.#GLANCE_ANIMATION_DURATION,
|
||||||
type: 'spring',
|
type: 'spring',
|
||||||
bounce: 0,
|
bounce: 0,
|
||||||
}
|
}
|
||||||
@@ -1012,7 +1008,6 @@
|
|||||||
this.browserWrapper.removeAttribute('animate');
|
this.browserWrapper.removeAttribute('animate');
|
||||||
|
|
||||||
if (!this.#currentParentTab) {
|
if (!this.#currentParentTab) {
|
||||||
this.closingGlance = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1068,6 +1063,7 @@
|
|||||||
this.contentWrapper = null;
|
this.contentWrapper = null;
|
||||||
|
|
||||||
lastCurrentTab.removeAttribute('zen-glance-tab');
|
lastCurrentTab.removeAttribute('zen-glance-tab');
|
||||||
|
lastCurrentTab._closingGlance = true;
|
||||||
|
|
||||||
this.#ignoreClose = true;
|
this.#ignoreClose = true;
|
||||||
lastCurrentTab.dispatchEvent(new Event('GlanceClose', { bubbles: true }));
|
lastCurrentTab.dispatchEvent(new Event('GlanceClose', { bubbles: true }));
|
||||||
|
|||||||
@@ -6,12 +6,18 @@ export class ZenGlanceChild extends JSWindowActorChild {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
this.clickListener = this.handleClick.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleEvent(event) {
|
async handleEvent(event) {
|
||||||
const handler = this[`on_${event.type}`];
|
switch (event.type) {
|
||||||
if (typeof handler === 'function') {
|
case 'DOMContentLoaded':
|
||||||
await handler.call(this, event);
|
await this.initiateGlance();
|
||||||
|
break;
|
||||||
|
case 'keydown':
|
||||||
|
this.onKeyDown(event);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,7 +25,13 @@ export class ZenGlanceChild extends JSWindowActorChild {
|
|||||||
this.#activationMethod = await this.sendQuery('ZenGlance:GetActivationMethod');
|
this.#activationMethod = await this.sendQuery('ZenGlance:GetActivationMethod');
|
||||||
}
|
}
|
||||||
|
|
||||||
#ensureOnlyKeyModifiers(event) {
|
async initiateGlance() {
|
||||||
|
this.mouseIsDown = false;
|
||||||
|
await this.#initActivationMethod();
|
||||||
|
this.contentWindow.document.addEventListener('click', this.clickListener, { capture: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
ensureOnlyKeyModifiers(event) {
|
||||||
return !(event.ctrlKey ^ event.altKey ^ event.shiftKey ^ event.metaKey);
|
return !(event.ctrlKey ^ event.altKey ^ event.shiftKey ^ event.metaKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +66,7 @@ export class ZenGlanceChild extends JSWindowActorChild {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
on_click(event) {
|
handleClick(event) {
|
||||||
if (event.button !== 0 || event.defaultPrevented) {
|
if (event.button !== 0 || event.defaultPrevented) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -67,7 +79,7 @@ export class ZenGlanceChild extends JSWindowActorChild {
|
|||||||
// The problem is that at that stage we don't know the rect or even what
|
// The problem is that at that stage we don't know the rect or even what
|
||||||
// element has been clicked, so we send the data here.
|
// element has been clicked, so we send the data here.
|
||||||
this.#sendClickDataToParent(target, elementToRecord);
|
this.#sendClickDataToParent(target, elementToRecord);
|
||||||
if (this.#ensureOnlyKeyModifiers(event)) {
|
if (this.ensureOnlyKeyModifiers(event)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const activationMethod = this.#activationMethod;
|
const activationMethod = this.#activationMethod;
|
||||||
@@ -88,7 +100,7 @@ export class ZenGlanceChild extends JSWindowActorChild {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
on_keydown(event) {
|
onKeyDown(event) {
|
||||||
if (event.defaultPrevented || event.key !== 'Escape') {
|
if (event.defaultPrevented || event.key !== 'Escape') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -96,8 +108,4 @@ export class ZenGlanceChild extends JSWindowActorChild {
|
|||||||
hasFocused: this.contentWindow.document.activeElement !== this.contentWindow.document.body,
|
hasFocused: this.contentWindow.document.activeElement !== this.contentWindow.document.body,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async on_DOMContentLoaded() {
|
|
||||||
await this.#initActivationMethod();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,4 +13,5 @@ DIRS += [
|
|||||||
"tests",
|
"tests",
|
||||||
"urlbar",
|
"urlbar",
|
||||||
"toolkit",
|
"toolkit",
|
||||||
|
"sessionstore",
|
||||||
]
|
]
|
||||||
|
|||||||
6
src/zen/sessionstore/SessionComponents.manifest
Normal file
6
src/zen/sessionstore/SessionComponents.manifest
Normal 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/.
|
||||||
|
|
||||||
|
# Browser global components initializing before UI startup
|
||||||
|
category browser-before-ui-startup resource:///modules/zen/ZenSessionManager.sys.mjs ZenSessionStore.init
|
||||||
40
src/zen/sessionstore/ZenSessionFile.sys.mjs
Normal file
40
src/zen/sessionstore/ZenSessionFile.sys.mjs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// 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 that changing this hidden pref will make the previous session file
|
||||||
|
// unused, causing a new session file to be created on next write.
|
||||||
|
const SHOULD_COMPRESS_FILE = Services.prefs.getBoolPref('zen.session-store.compress-file', true);
|
||||||
|
|
||||||
|
const FILE_NAME = SHOULD_COMPRESS_FILE ? 'zen-sessions.jsonlz4' : 'zen-sessions.json';
|
||||||
|
|
||||||
|
export class nsZenSessionFile {
|
||||||
|
#path = PathUtils.join(PathUtils.profileDir, FILE_NAME);
|
||||||
|
#sidebar = [];
|
||||||
|
|
||||||
|
async read() {
|
||||||
|
try {
|
||||||
|
const data = await IOUtils.readJSON(this.#path, { compress: SHOULD_COMPRESS_FILE });
|
||||||
|
this.#sidebar = data.sidebar || [];
|
||||||
|
} catch {
|
||||||
|
// File doesn't exist yet, that's fine.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get sidebar() {
|
||||||
|
return this.#sidebar;
|
||||||
|
}
|
||||||
|
|
||||||
|
set sidebar(data) {
|
||||||
|
this.#sidebar = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
async #write(data) {
|
||||||
|
await IOUtils.writeJSON(this.#path, data, { compress: SHOULD_COMPRESS_FILE });
|
||||||
|
}
|
||||||
|
|
||||||
|
async store() {
|
||||||
|
const data = { sidebar: this.#sidebar };
|
||||||
|
await this.#write(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
163
src/zen/sessionstore/ZenSessionManager.sys.mjs
Normal file
163
src/zen/sessionstore/ZenSessionManager.sys.mjs
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
// 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 lazy = {};
|
||||||
|
|
||||||
|
ChromeUtils.defineESModuleGetters(lazy, {
|
||||||
|
nsZenSessionFile: 'resource:///modules/zen/ZenSessionFile.sys.mjs',
|
||||||
|
PrivateBrowsingUtils: 'resource://gre/modules/PrivateBrowsingUtils.sys.mjs',
|
||||||
|
BrowserWindowTracker: 'resource:///modules/BrowserWindowTracker.sys.mjs',
|
||||||
|
TabGroupState: 'resource:///modules/sessionstore/TabGroupState.sys.mjs',
|
||||||
|
SessionStore: 'resource:///modules/sessionstore/SessionStore.sys.mjs',
|
||||||
|
});
|
||||||
|
|
||||||
|
const LAZY_COLLECT_THRESHOLD = 5 * 60 * 1000; // 5 minutes
|
||||||
|
const OBSERVING = ['sessionstore-state-write-complete', 'browser-window-before-show'];
|
||||||
|
|
||||||
|
class nsZenSessionManager {
|
||||||
|
#file;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.#file = new lazy.nsZenSessionFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called from SessionComponents.manifest on app-startup
|
||||||
|
init() {
|
||||||
|
this.#initObservers();
|
||||||
|
}
|
||||||
|
|
||||||
|
async readFile() {
|
||||||
|
await this.#file.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
onFileRead(initialState) {
|
||||||
|
for (const winData of initialState.windows || []) {
|
||||||
|
this.restoreWindowData(winData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#initObservers() {
|
||||||
|
for (let topic of OBSERVING) {
|
||||||
|
Services.obs.addObserver(this, topic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get #sidebar() {
|
||||||
|
return this.#file.sidebar;
|
||||||
|
}
|
||||||
|
|
||||||
|
set #sidebar(data) {
|
||||||
|
this.#file.sidebar = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
observe(aSubject, aTopic) {
|
||||||
|
switch (aTopic) {
|
||||||
|
case 'sessionstore-state-write-complete': {
|
||||||
|
this.#saveState(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'browser-window-before-show': // catch new windows
|
||||||
|
this.#onBeforeBrowserWindowShown(aSubject);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Handles the browser-window-before-show observer notification. */
|
||||||
|
#onBeforeBrowserWindowShown(aWindow) {
|
||||||
|
// TODO: Initialize new window
|
||||||
|
void aWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
get #topMostWindow() {
|
||||||
|
return lazy.BrowserWindowTracker.getTopWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the current session state. Collects data and writes to disk.
|
||||||
|
*
|
||||||
|
* @param forceUpdateAllWindows (optional)
|
||||||
|
* Forces us to recollect data for all windows and will bypass and
|
||||||
|
* update the corresponding caches.
|
||||||
|
*/
|
||||||
|
async #saveState(forceUpdateAllWindows = false) {
|
||||||
|
if (lazy.PrivateBrowsingUtils.permanentPrivateBrowsing) {
|
||||||
|
// Don't save (or even collect) anything in permanent private
|
||||||
|
// browsing mode
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
// Collect an initial snapshot of window data before we do the flush.
|
||||||
|
const window = this.#topMostWindow;
|
||||||
|
// We don't have any normal windows or no windows at all
|
||||||
|
if (!window) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.#collectWindowData(this.#topMostWindow, forceUpdateAllWindows);
|
||||||
|
this.#file.store();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collects session data for a given window.
|
||||||
|
*
|
||||||
|
* @param window
|
||||||
|
* The window to collect data for.
|
||||||
|
* @param forceUpdate
|
||||||
|
* Forces us to recollect data and will bypass and update the
|
||||||
|
* corresponding caches.
|
||||||
|
*/
|
||||||
|
#collectWindowData(window, forceUpdate = false) {
|
||||||
|
let sidebarData = this.#sidebar;
|
||||||
|
if (!sidebarData || forceUpdate) {
|
||||||
|
sidebarData = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it hasn't changed, don't update.
|
||||||
|
if (
|
||||||
|
!forceUpdate &&
|
||||||
|
sidebarData.lastCollected &&
|
||||||
|
Date.now() - sidebarData.lastCollected < LAZY_COLLECT_THRESHOLD
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sidebarData.lastCollected = Date.now();
|
||||||
|
this.#collectTabsData(window, sidebarData);
|
||||||
|
this.#sidebar = sidebarData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collects session data for all tabs in a given window.
|
||||||
|
*
|
||||||
|
* @param aWindow
|
||||||
|
* The window to collect tab data for.
|
||||||
|
* @param winData
|
||||||
|
* The window data object to populate.
|
||||||
|
*/
|
||||||
|
#collectTabsData(aWindow, sidebarData) {
|
||||||
|
const winData = lazy.SessionStore.getWindowState(aWindow).windows[0];
|
||||||
|
if (!winData) return;
|
||||||
|
sidebarData.tabs = winData.tabs;
|
||||||
|
sidebarData.folders = winData.folders;
|
||||||
|
sidebarData.splitViewData = winData.splitViewData;
|
||||||
|
sidebarData.groups = winData.groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
restoreWindowData(aWindowData) {
|
||||||
|
const sidebar = this.#file.sidebar;
|
||||||
|
if (!sidebar) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
aWindowData.tabs = sidebar.tabs || [];
|
||||||
|
aWindowData.splitViewData = sidebar.splitViewData;
|
||||||
|
aWindowData.folders = sidebar.folders;
|
||||||
|
aWindowData.groups = sidebar.groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
getNewWindowData(aWindows) {
|
||||||
|
let newWindow = { ...Cu.cloneInto(aWindows[Object.keys(aWindows)[0]], {}), ...this.#sidebar };
|
||||||
|
return { windows: [newWindow] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ZenSessionStore = new nsZenSessionManager();
|
||||||
8
src/zen/sessionstore/moz.build
Normal file
8
src/zen/sessionstore/moz.build
Normal 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/.
|
||||||
|
|
||||||
|
EXTRA_JS_MODULES.zen += [
|
||||||
|
"ZenSessionFile.sys.mjs",
|
||||||
|
"ZenSessionManager.sys.mjs",
|
||||||
|
]
|
||||||
@@ -5,23 +5,7 @@
|
|||||||
const lazy = {};
|
const lazy = {};
|
||||||
|
|
||||||
class ZenPinnedTabsObserver {
|
class ZenPinnedTabsObserver {
|
||||||
static ALL_EVENTS = [
|
static ALL_EVENTS = ['TabPinned', 'TabUnpinned'];
|
||||||
'TabPinned',
|
|
||||||
'TabUnpinned',
|
|
||||||
'TabMove',
|
|
||||||
'TabGroupCreate',
|
|
||||||
'TabGroupRemoved',
|
|
||||||
'TabGroupMoved',
|
|
||||||
'ZenFolderRenamed',
|
|
||||||
'ZenFolderIconChanged',
|
|
||||||
'TabGroupCollapse',
|
|
||||||
'TabGroupExpand',
|
|
||||||
'TabGrouped',
|
|
||||||
'TabUngrouped',
|
|
||||||
'ZenFolderChangedWorkspace',
|
|
||||||
'TabAddedToEssentials',
|
|
||||||
'TabRemovedFromEssentials',
|
|
||||||
];
|
|
||||||
|
|
||||||
#listeners = [];
|
#listeners = [];
|
||||||
|
|
||||||
@@ -101,24 +85,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
onTabIconChanged(tab, url = null) {
|
onTabIconChanged(tab, url = null) {
|
||||||
|
tab.dispatchEvent(new CustomEvent('ZenTabIconChanged', { bubbles: true, detail: { tab } }));
|
||||||
const iconUrl = url ?? tab.iconImage.src;
|
const iconUrl = url ?? tab.iconImage.src;
|
||||||
if (!iconUrl && tab.hasAttribute('zen-pin-id')) {
|
|
||||||
try {
|
|
||||||
setTimeout(async () => {
|
|
||||||
const favicon = await this.getFaviconAsBase64(tab.linkedBrowser.currentURI);
|
|
||||||
if (favicon) {
|
|
||||||
gBrowser.setIcon(tab, favicon);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch {
|
|
||||||
// Handle error
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (tab.hasAttribute('zen-essential')) {
|
if (tab.hasAttribute('zen-essential')) {
|
||||||
tab.style.setProperty('--zen-essential-tab-icon', `url(${iconUrl})`);
|
tab.style.setProperty('--zen-essential-tab-icon', `url(${iconUrl})`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
_onTabResetPinButton(event, tab) {
|
_onTabResetPinButton(event, tab) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
@@ -148,261 +120,6 @@
|
|||||||
return lazy.zenTabsEssentialsMax;
|
return lazy.zenTabsEssentialsMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
async refreshPinnedTabs({ init = false } = {}) {
|
|
||||||
if (!this.enabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await ZenPinnedTabsStorage.promiseInitialized;
|
|
||||||
await this.#initializePinsCache();
|
|
||||||
setTimeout(async () => {
|
|
||||||
// Execute in a separate task to avoid blocking the main thread
|
|
||||||
await SessionStore.promiseAllWindowsRestored;
|
|
||||||
await gZenWorkspaces.promiseInitialized;
|
|
||||||
await this.#initializePinnedTabs(init);
|
|
||||||
if (init) {
|
|
||||||
this._hasFinishedLoading = true;
|
|
||||||
}
|
|
||||||
}, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
async #initializePinsCache() {
|
|
||||||
try {
|
|
||||||
// Get pin data
|
|
||||||
const pins = await ZenPinnedTabsStorage.getPins();
|
|
||||||
|
|
||||||
// Enhance pins with favicons
|
|
||||||
this._pinsCache = await Promise.all(
|
|
||||||
pins.map(async (pin) => {
|
|
||||||
try {
|
|
||||||
if (pin.isGroup) {
|
|
||||||
return pin; // Skip groups for now
|
|
||||||
}
|
|
||||||
const image = await this.getFaviconAsBase64(Services.io.newURI(pin.url));
|
|
||||||
return {
|
|
||||||
...pin,
|
|
||||||
iconUrl: image || null,
|
|
||||||
};
|
|
||||||
} catch {
|
|
||||||
// If favicon fetch fails, continue without icon
|
|
||||||
return {
|
|
||||||
...pin,
|
|
||||||
iconUrl: null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
} catch (ex) {
|
|
||||||
console.error('Failed to initialize pins cache:', ex);
|
|
||||||
this._pinsCache = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log(`Initialized pins cache with ${this._pinsCache.length} pins`);
|
|
||||||
return this._pinsCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
#finishedInitializingPins() {
|
|
||||||
if (this.hasInitializedPins) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._resolvePinnedInitializedInternal();
|
|
||||||
delete this._resolvePinnedInitializedInternal;
|
|
||||||
this.hasInitializedPins = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
async #initializePinnedTabs(init = false) {
|
|
||||||
const pins = this._pinsCache;
|
|
||||||
if (!pins?.length || !init) {
|
|
||||||
this.#finishedInitializingPins();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const pinnedTabsByUUID = new Map();
|
|
||||||
const pinsToCreate = new Set(pins.map((p) => p.uuid));
|
|
||||||
|
|
||||||
// First pass: identify existing tabs and remove those without pins
|
|
||||||
for (let tab of gZenWorkspaces.allStoredTabs) {
|
|
||||||
const pinId = tab.getAttribute('zen-pin-id');
|
|
||||||
if (!pinId) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pinsToCreate.has(pinId)) {
|
|
||||||
// This is a valid pinned tab that matches a pin
|
|
||||||
pinnedTabsByUUID.set(pinId, tab);
|
|
||||||
pinsToCreate.delete(pinId);
|
|
||||||
|
|
||||||
if (lazy.zenPinnedTabRestorePinnedTabsToPinnedUrl && init) {
|
|
||||||
this._resetTabToStoredState(tab);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// This is a pinned tab that no longer has a corresponding pin
|
|
||||||
gBrowser.removeTab(tab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const group of gZenWorkspaces.allTabGroups) {
|
|
||||||
const pinId = group.getAttribute('zen-pin-id');
|
|
||||||
if (!pinId) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (pinsToCreate.has(pinId)) {
|
|
||||||
// This is a valid pinned group that matches a pin
|
|
||||||
pinsToCreate.delete(pinId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Second pass: For every existing tab, update its label
|
|
||||||
// and set 'zen-has-static-label' attribute if it's been edited
|
|
||||||
for (let pin of pins) {
|
|
||||||
const tab = pinnedTabsByUUID.get(pin.uuid);
|
|
||||||
if (!tab) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
tab.removeAttribute('zen-has-static-label'); // So we can set it again
|
|
||||||
if (pin.title && pin.editedTitle) {
|
|
||||||
gBrowser._setTabLabel(tab, pin.title, { beforeTabOpen: true });
|
|
||||||
tab.setAttribute('zen-has-static-label', 'true');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const groups = new Map();
|
|
||||||
const pendingTabsInsideGroups = {};
|
|
||||||
|
|
||||||
// Third pass: create new tabs for pins that don't have tabs
|
|
||||||
for (let pin of pins) {
|
|
||||||
try {
|
|
||||||
if (!pinsToCreate.has(pin.uuid)) {
|
|
||||||
continue; // Skip pins that already have tabs
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pin.isGroup) {
|
|
||||||
const tabs = [];
|
|
||||||
// If there's already existing tabs, let's use them
|
|
||||||
for (const [uuid, existingTab] of pinnedTabsByUUID) {
|
|
||||||
const pinObject = this._pinsCache.find((p) => p.uuid === uuid);
|
|
||||||
if (pinObject && pinObject.parentUuid === pin.uuid) {
|
|
||||||
tabs.push(existingTab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// We still need to iterate through pending tabs since the database
|
|
||||||
// query doesn't guarantee the order of insertion
|
|
||||||
for (const [parentUuid, folderTabs] of Object.entries(pendingTabsInsideGroups)) {
|
|
||||||
if (parentUuid === pin.uuid) {
|
|
||||||
tabs.push(...folderTabs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const group = gZenFolders.createFolder(tabs, {
|
|
||||||
label: pin.title,
|
|
||||||
collapsed: pin.isFolderCollapsed,
|
|
||||||
initialPinId: pin.uuid,
|
|
||||||
workspaceId: pin.workspaceUuid,
|
|
||||||
insertAfter:
|
|
||||||
groups.get(pin.parentUuid)?.querySelector('.tab-group-container')?.lastChild ||
|
|
||||||
null,
|
|
||||||
});
|
|
||||||
gZenFolders.setFolderUserIcon(group, pin.folderIcon);
|
|
||||||
groups.set(pin.uuid, group);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let params = {
|
|
||||||
skipAnimation: true,
|
|
||||||
allowInheritPrincipal: false,
|
|
||||||
skipBackgroundNotify: true,
|
|
||||||
userContextId: pin.containerTabId || 0,
|
|
||||||
createLazyBrowser: true,
|
|
||||||
skipLoad: true,
|
|
||||||
noInitialLabel: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create and initialize the tab
|
|
||||||
let newTab = gBrowser.addTrustedTab(pin.url, params);
|
|
||||||
newTab.setAttribute('zenDefaultUserContextId', true);
|
|
||||||
|
|
||||||
// Set initial label/title
|
|
||||||
if (pin.title) {
|
|
||||||
gBrowser.setInitialTabTitle(newTab, pin.title);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the icon if we have it cached
|
|
||||||
if (pin.iconUrl) {
|
|
||||||
gBrowser.setIcon(newTab, pin.iconUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
newTab.setAttribute('zen-pin-id', pin.uuid);
|
|
||||||
|
|
||||||
if (pin.workspaceUuid) {
|
|
||||||
newTab.setAttribute('zen-workspace-id', pin.workspaceUuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pin.isEssential) {
|
|
||||||
newTab.setAttribute('zen-essential', 'true');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pin.editedTitle) {
|
|
||||||
newTab.setAttribute('zen-has-static-label', 'true');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize browser state if needed
|
|
||||||
if (!newTab.linkedBrowser._remoteAutoRemoved) {
|
|
||||||
let state = {
|
|
||||||
entries: [
|
|
||||||
{
|
|
||||||
url: pin.url,
|
|
||||||
title: pin.title,
|
|
||||||
triggeringPrincipal_base64: E10SUtils.SERIALIZED_SYSTEMPRINCIPAL,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
userContextId: pin.containerTabId || 0,
|
|
||||||
image: pin.iconUrl,
|
|
||||||
};
|
|
||||||
|
|
||||||
SessionStore.setTabState(newTab, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log(`Created new pinned tab for pin ${pin.uuid} (isEssential: ${pin.isEssential})`);
|
|
||||||
gBrowser.pinTab(newTab);
|
|
||||||
|
|
||||||
if (pin.parentUuid) {
|
|
||||||
const parentGroup = groups.get(pin.parentUuid);
|
|
||||||
if (parentGroup) {
|
|
||||||
parentGroup.querySelector('.tab-group-container').appendChild(newTab);
|
|
||||||
} else {
|
|
||||||
if (pendingTabsInsideGroups[pin.parentUuid]) {
|
|
||||||
pendingTabsInsideGroups[pin.parentUuid].push(newTab);
|
|
||||||
} else {
|
|
||||||
pendingTabsInsideGroups[pin.parentUuid] = [newTab];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!pin.isEssential) {
|
|
||||||
const container = gZenWorkspaces.workspaceElement(
|
|
||||||
pin.workspaceUuid
|
|
||||||
)?.pinnedTabsContainer;
|
|
||||||
if (container) {
|
|
||||||
container.insertBefore(newTab, container.lastChild);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gZenWorkspaces.getEssentialsSection(pin.containerTabId).appendChild(newTab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gBrowser.tabContainer._invalidateCachedTabs();
|
|
||||||
newTab.initialize();
|
|
||||||
} catch (ex) {
|
|
||||||
console.error('Failed to initialize pinned tabs:', ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
this.#finishedInitializingPins();
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
gBrowser._updateTabBarForPinnedTabs();
|
|
||||||
gZenUIManager.updateTabsToolbar();
|
|
||||||
}
|
|
||||||
|
|
||||||
_onPinnedTabEvent(action, event) {
|
_onPinnedTabEvent(action, event) {
|
||||||
if (!this.enabled) return;
|
if (!this.enabled) return;
|
||||||
const tab = event.target;
|
const tab = event.target;
|
||||||
@@ -412,230 +129,22 @@
|
|||||||
}
|
}
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 'TabPinned':
|
case 'TabPinned':
|
||||||
case 'TabAddedToEssentials':
|
|
||||||
tab._zenClickEventListener = this._zenClickEventListener;
|
tab._zenClickEventListener = this._zenClickEventListener;
|
||||||
tab.addEventListener('click', tab._zenClickEventListener);
|
tab.addEventListener('click', tab._zenClickEventListener);
|
||||||
this._setPinnedAttributes(tab);
|
|
||||||
break;
|
break;
|
||||||
case 'TabRemovedFromEssentials':
|
|
||||||
if (tab.pinned) {
|
|
||||||
this.#onTabMove(tab);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// [Fall through]
|
// [Fall through]
|
||||||
case 'TabUnpinned':
|
case 'TabUnpinned':
|
||||||
this._removePinnedAttributes(tab);
|
|
||||||
if (tab._zenClickEventListener) {
|
if (tab._zenClickEventListener) {
|
||||||
tab.removeEventListener('click', tab._zenClickEventListener);
|
tab.removeEventListener('click', tab._zenClickEventListener);
|
||||||
delete tab._zenClickEventListener;
|
delete tab._zenClickEventListener;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'TabMove':
|
|
||||||
this.#onTabMove(tab);
|
|
||||||
break;
|
|
||||||
case 'TabGroupCreate':
|
|
||||||
this.#onTabGroupCreate(event);
|
|
||||||
break;
|
|
||||||
case 'TabGroupRemoved':
|
|
||||||
this.#onTabGroupRemoved(event);
|
|
||||||
break;
|
|
||||||
case 'TabGroupMoved':
|
|
||||||
this.#onTabGroupMoved(event);
|
|
||||||
break;
|
|
||||||
case 'ZenFolderRenamed':
|
|
||||||
case 'ZenFolderIconChanged':
|
|
||||||
case 'TabGroupCollapse':
|
|
||||||
case 'TabGroupExpand':
|
|
||||||
case 'ZenFolderChangedWorkspace':
|
|
||||||
this.#updateGroupInfo(event.originalTarget);
|
|
||||||
break;
|
|
||||||
case 'TabGrouped':
|
|
||||||
this.#onTabGrouped(event);
|
|
||||||
break;
|
|
||||||
case 'TabUngrouped':
|
|
||||||
this.#onTabUngrouped(event);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
console.warn('ZenPinnedTabManager: Unhandled tab event', action);
|
console.warn('ZenPinnedTabManager: Unhandled tab event', action);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async #onTabGroupCreate(event) {
|
|
||||||
const group = event.originalTarget;
|
|
||||||
if (!group.isZenFolder) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (group.hasAttribute('zen-pin-id')) {
|
|
||||||
return; // Group already exists in storage
|
|
||||||
}
|
|
||||||
const workspaceId = group.getAttribute('zen-workspace-id');
|
|
||||||
let id = await ZenPinnedTabsStorage.createGroup(
|
|
||||||
group.name,
|
|
||||||
group.iconURL,
|
|
||||||
group.collapsed,
|
|
||||||
workspaceId,
|
|
||||||
group.getAttribute('zen-pin-id'),
|
|
||||||
group._pPos
|
|
||||||
);
|
|
||||||
group.setAttribute('zen-pin-id', id);
|
|
||||||
for (const tab of group.tabs) {
|
|
||||||
// Only add it if the tab is directly under the group
|
|
||||||
if (
|
|
||||||
tab.pinned &&
|
|
||||||
tab.hasAttribute('zen-pin-id') &&
|
|
||||||
tab.group === group &&
|
|
||||||
this.hasInitializedPins
|
|
||||||
) {
|
|
||||||
const tabPinId = tab.getAttribute('zen-pin-id');
|
|
||||||
await ZenPinnedTabsStorage.addTabToGroup(tabPinId, id, /* position */ tab._pPos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await this.refreshPinnedTabs();
|
|
||||||
}
|
|
||||||
|
|
||||||
async #onTabGrouped(event) {
|
|
||||||
const tab = event.detail;
|
|
||||||
const group = tab.group;
|
|
||||||
if (!group.isZenFolder) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const pinId = group.getAttribute('zen-pin-id');
|
|
||||||
const tabPinId = tab.getAttribute('zen-pin-id');
|
|
||||||
const tabPin = this._pinsCache?.find((p) => p.uuid === tabPinId);
|
|
||||||
if (!tabPin || !tabPin.group) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ZenPinnedTabsStorage.addTabToGroup(tabPinId, pinId, /* position */ tab._pPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
async #onTabUngrouped(event) {
|
|
||||||
const tab = event.detail;
|
|
||||||
const group = tab.group;
|
|
||||||
if (!group?.isZenFolder) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const tabPinId = tab.getAttribute('zen-pin-id');
|
|
||||||
const tabPin = this._pinsCache?.find((p) => p.uuid === tabPinId);
|
|
||||||
if (!tabPin) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ZenPinnedTabsStorage.removeTabFromGroup(tabPinId, /* position */ tab._pPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
async #updateGroupInfo(group) {
|
|
||||||
if (!group?.isZenFolder) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const pinId = group.getAttribute('zen-pin-id');
|
|
||||||
const groupPin = this._pinsCache?.find((p) => p.uuid === pinId);
|
|
||||||
if (groupPin) {
|
|
||||||
groupPin.title = group.name;
|
|
||||||
groupPin.folderIcon = group.iconURL;
|
|
||||||
groupPin.isFolderCollapsed = group.collapsed;
|
|
||||||
groupPin.position = group._pPos;
|
|
||||||
groupPin.parentUuid = group.group?.getAttribute('zen-pin-id') || null;
|
|
||||||
groupPin.workspaceUuid = group.getAttribute('zen-workspace-id') || null;
|
|
||||||
await this.savePin(groupPin);
|
|
||||||
for (const item of group.allItems) {
|
|
||||||
if (gBrowser.isTabGroup(item)) {
|
|
||||||
await this.#updateGroupInfo(item);
|
|
||||||
} else {
|
|
||||||
await this.#onTabMove(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async #onTabGroupRemoved(event) {
|
|
||||||
const group = event.originalTarget;
|
|
||||||
if (!group.isZenFolder) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await ZenPinnedTabsStorage.removePin(group.getAttribute('zen-pin-id'));
|
|
||||||
group.removeAttribute('zen-pin-id');
|
|
||||||
}
|
|
||||||
|
|
||||||
async #onTabGroupMoved(event) {
|
|
||||||
const group = event.originalTarget;
|
|
||||||
if (!group.isZenFolder) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const newIndex = group._pPos;
|
|
||||||
const pinId = group.getAttribute('zen-pin-id');
|
|
||||||
if (!pinId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (const tab of group.allItemsRecursive) {
|
|
||||||
if (tab.pinned && tab.getAttribute('zen-pin-id') === pinId) {
|
|
||||||
const pin = this._pinsCache.find((p) => p.uuid === pinId);
|
|
||||||
if (pin) {
|
|
||||||
pin.position = tab._pPos;
|
|
||||||
pin.parentUuid = tab.group?.getAttribute('zen-pin-id') || null;
|
|
||||||
pin.workspaceUuid = group.getAttribute('zen-workspace-id');
|
|
||||||
await this.savePin(pin, false);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const groupPin = this._pinsCache?.find((p) => p.uuid === pinId);
|
|
||||||
if (groupPin) {
|
|
||||||
groupPin.position = newIndex;
|
|
||||||
groupPin.parentUuid = group.group?.getAttribute('zen-pin-id');
|
|
||||||
groupPin.workspaceUuid = group.getAttribute('zen-workspace-id');
|
|
||||||
await this.savePin(groupPin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async #onTabMove(tab) {
|
|
||||||
if (!tab.pinned || !this._pinsCache) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const allTabs = [...gBrowser.tabs, ...gBrowser.tabGroups];
|
|
||||||
for (let i = 0; i < allTabs.length; i++) {
|
|
||||||
const otherTab = allTabs[i];
|
|
||||||
if (
|
|
||||||
otherTab.pinned &&
|
|
||||||
otherTab.getAttribute('zen-pin-id') !== tab.getAttribute('zen-pin-id')
|
|
||||||
) {
|
|
||||||
const actualPin = this._pinsCache.find(
|
|
||||||
(pin) => pin.uuid === otherTab.getAttribute('zen-pin-id')
|
|
||||||
);
|
|
||||||
if (!actualPin) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
actualPin.position = otherTab._pPos;
|
|
||||||
actualPin.workspaceUuid = otherTab.getAttribute('zen-workspace-id');
|
|
||||||
actualPin.parentUuid = otherTab.group?.getAttribute('zen-pin-id') || null;
|
|
||||||
await this.savePin(actualPin, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const actualPin = this._pinsCache.find((pin) => pin.uuid === tab.getAttribute('zen-pin-id'));
|
|
||||||
|
|
||||||
if (!actualPin) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
actualPin.position = tab._pPos;
|
|
||||||
actualPin.isEssential = tab.hasAttribute('zen-essential');
|
|
||||||
actualPin.parentUuid = tab.group?.getAttribute('zen-pin-id') || null;
|
|
||||||
actualPin.workspaceUuid = tab.getAttribute('zen-workspace-id') || null;
|
|
||||||
|
|
||||||
// There was a bug where the title and hasStaticLabel attribute were not being set
|
|
||||||
// This is a workaround to fix that
|
|
||||||
if (tab.hasAttribute('zen-has-static-label')) {
|
|
||||||
actualPin.editedTitle = true;
|
|
||||||
actualPin.title = tab.label;
|
|
||||||
}
|
|
||||||
await this.savePin(actualPin);
|
|
||||||
tab.dispatchEvent(
|
|
||||||
new CustomEvent('ZenPinnedTabMoved', {
|
|
||||||
detail: { tab },
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async _onTabClick(e) {
|
async _onTabClick(e) {
|
||||||
const tab = e.target?.closest('tab');
|
const tab = e.target?.closest('tab');
|
||||||
if (e.button === 1 && tab) {
|
if (e.button === 1 && tab) {
|
||||||
@@ -665,106 +174,10 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const browser = tab.linkedBrowser;
|
|
||||||
|
|
||||||
const pin = this._pinsCache.find((pin) => pin.uuid === tab.getAttribute('zen-pin-id'));
|
|
||||||
|
|
||||||
if (!pin) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const userContextId = tab.getAttribute('usercontextid');
|
|
||||||
|
|
||||||
pin.title = tab.label || browser.contentTitle;
|
|
||||||
pin.url = browser.currentURI.spec;
|
|
||||||
pin.workspaceUuid = tab.getAttribute('zen-workspace-id');
|
|
||||||
pin.userContextId = userContextId ? parseInt(userContextId, 10) : 0;
|
|
||||||
|
|
||||||
await this.savePin(pin);
|
|
||||||
this.resetPinChangedUrl(tab);
|
this.resetPinChangedUrl(tab);
|
||||||
await this.refreshPinnedTabs();
|
|
||||||
gZenUIManager.showToast('zen-pinned-tab-replaced');
|
gZenUIManager.showToast('zen-pinned-tab-replaced');
|
||||||
}
|
}
|
||||||
|
|
||||||
async _setPinnedAttributes(tab) {
|
|
||||||
if (
|
|
||||||
tab.hasAttribute('zen-pin-id') ||
|
|
||||||
!this._hasFinishedLoading ||
|
|
||||||
tab.hasAttribute('zen-empty-tab')
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log(`Setting pinned attributes for tab ${tab.linkedBrowser.currentURI.spec}`);
|
|
||||||
const browser = tab.linkedBrowser;
|
|
||||||
|
|
||||||
const uuid = gZenUIManager.generateUuidv4();
|
|
||||||
const userContextId = tab.getAttribute('usercontextid');
|
|
||||||
|
|
||||||
let entry = null;
|
|
||||||
|
|
||||||
if (tab.getAttribute('zen-pinned-entry')) {
|
|
||||||
entry = JSON.parse(tab.getAttribute('zen-pinned-entry'));
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.savePin({
|
|
||||||
uuid,
|
|
||||||
title: entry?.title || tab.label || browser.contentTitle,
|
|
||||||
url: entry?.url || browser.currentURI.spec,
|
|
||||||
containerTabId: userContextId ? parseInt(userContextId, 10) : 0,
|
|
||||||
workspaceUuid: tab.getAttribute('zen-workspace-id'),
|
|
||||||
isEssential: tab.getAttribute('zen-essential') === 'true',
|
|
||||||
parentUuid: tab.group?.getAttribute('zen-pin-id') || null,
|
|
||||||
position: tab._pPos,
|
|
||||||
});
|
|
||||||
|
|
||||||
tab.setAttribute('zen-pin-id', uuid);
|
|
||||||
tab.dispatchEvent(
|
|
||||||
new CustomEvent('ZenPinnedTabCreated', {
|
|
||||||
detail: { tab },
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
// This is used while migrating old pins to new system - we don't want to refresh when migrating
|
|
||||||
if (tab.getAttribute('zen-pinned-entry')) {
|
|
||||||
tab.removeAttribute('zen-pinned-entry');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.onLocationChange(browser);
|
|
||||||
await this.refreshPinnedTabs();
|
|
||||||
}
|
|
||||||
|
|
||||||
async _removePinnedAttributes(tab, isClosing = false) {
|
|
||||||
tab.removeAttribute('zen-has-static-label');
|
|
||||||
if (!tab.getAttribute('zen-pin-id') || this._temporarilyUnpiningEssential) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Services.startup.shuttingDown || window.skipNextCanClose) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log(`Removing pinned attributes for tab ${tab.getAttribute('zen-pin-id')}`);
|
|
||||||
await ZenPinnedTabsStorage.removePin(tab.getAttribute('zen-pin-id'));
|
|
||||||
this.resetPinChangedUrl(tab);
|
|
||||||
|
|
||||||
if (!isClosing) {
|
|
||||||
tab.removeAttribute('zen-pin-id');
|
|
||||||
tab.removeAttribute('zen-essential'); // Just in case
|
|
||||||
|
|
||||||
if (!tab.hasAttribute('zen-workspace-id') && gZenWorkspaces.workspaceEnabled) {
|
|
||||||
const workspace = await gZenWorkspaces.getActiveWorkspace();
|
|
||||||
tab.setAttribute('zen-workspace-id', workspace.uuid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await this.refreshPinnedTabs();
|
|
||||||
tab.dispatchEvent(
|
|
||||||
new CustomEvent('ZenPinnedTabRemoved', {
|
|
||||||
detail: { tab },
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_initClosePinnedTabShortcut() {
|
_initClosePinnedTabShortcut() {
|
||||||
let cmdClose = document.getElementById('cmd_close');
|
let cmdClose = document.getElementById('cmd_close');
|
||||||
|
|
||||||
@@ -773,21 +186,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async savePin(pin, notifyObservers = true) {
|
|
||||||
if (!this.hasInitializedPins && !gZenUIManager.testingEnabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const existingPin = this._pinsCache.find((p) => p.uuid === pin.uuid);
|
|
||||||
if (existingPin) {
|
|
||||||
Object.assign(existingPin, pin);
|
|
||||||
} else {
|
|
||||||
// We shouldn't need it, but just in case there's
|
|
||||||
// a race condition while making new pinned tabs.
|
|
||||||
this._pinsCache.push(pin);
|
|
||||||
}
|
|
||||||
await ZenPinnedTabsStorage.savePin(pin, notifyObservers);
|
|
||||||
}
|
|
||||||
|
|
||||||
async onCloseTabShortcut(
|
async onCloseTabShortcut(
|
||||||
event,
|
event,
|
||||||
selectedTab = gBrowser.selectedTab,
|
selectedTab = gBrowser.selectedTab,
|
||||||
@@ -1010,12 +408,6 @@
|
|||||||
tab.removeAttribute('zen-workspace-id');
|
tab.removeAttribute('zen-workspace-id');
|
||||||
}
|
}
|
||||||
if (tab.pinned && tab.hasAttribute('zen-pin-id')) {
|
if (tab.pinned && tab.hasAttribute('zen-pin-id')) {
|
||||||
const pin = this._pinsCache.find((pin) => pin.uuid === tab.getAttribute('zen-pin-id'));
|
|
||||||
if (pin) {
|
|
||||||
pin.isEssential = true;
|
|
||||||
pin.workspaceUuid = null;
|
|
||||||
this.savePin(pin);
|
|
||||||
}
|
|
||||||
gBrowser.zenHandleTabMove(tab, () => {
|
gBrowser.zenHandleTabMove(tab, () => {
|
||||||
if (tab.ownerGlobal !== window) {
|
if (tab.ownerGlobal !== window) {
|
||||||
tab = gBrowser.adoptTab(tab, {
|
tab = gBrowser.adoptTab(tab, {
|
||||||
@@ -1406,11 +798,8 @@
|
|||||||
return document.documentElement.getAttribute('zen-sidebar-expanded') === 'true';
|
return document.documentElement.getAttribute('zen-sidebar-expanded') === 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
async updatePinTitle(tab, newTitle, isEdited = true, notifyObservers = true) {
|
async updatePinTitle(tab, newTitle, isEdited = true) {
|
||||||
const uuid = tab.getAttribute('zen-pin-id');
|
const uuid = tab.getAttribute('zen-pin-id');
|
||||||
await ZenPinnedTabsStorage.updatePinTitle(uuid, newTitle, isEdited, notifyObservers);
|
|
||||||
|
|
||||||
await this.refreshPinnedTabs();
|
|
||||||
|
|
||||||
const browsers = Services.wm.getEnumerator('navigator:browser');
|
const browsers = Services.wm.getEnumerator('navigator:browser');
|
||||||
|
|
||||||
@@ -1555,6 +944,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async onTabLabelChanged(tab) {
|
async onTabLabelChanged(tab) {
|
||||||
|
tab.dispatchEvent(new CustomEvent('ZenTabLabelChanged', { detail: { tab } }));
|
||||||
if (!this._pinsCache) {
|
if (!this._pinsCache) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,635 +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 ZenPinnedTabsStorage = {
|
|
||||||
async init() {
|
|
||||||
await this._ensureTable();
|
|
||||||
},
|
|
||||||
|
|
||||||
async _ensureTable() {
|
|
||||||
await PlacesUtils.withConnectionWrapper('ZenPinnedTabsStorage._ensureTable', async (db) => {
|
|
||||||
// Create the pins table if it doesn't exist
|
|
||||||
await db.execute(`
|
|
||||||
CREATE TABLE IF NOT EXISTS zen_pins (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
uuid TEXT UNIQUE NOT NULL,
|
|
||||||
title TEXT NOT NULL,
|
|
||||||
url TEXT,
|
|
||||||
container_id INTEGER,
|
|
||||||
workspace_uuid TEXT,
|
|
||||||
position INTEGER NOT NULL DEFAULT 0,
|
|
||||||
is_essential BOOLEAN NOT NULL DEFAULT 0,
|
|
||||||
is_group BOOLEAN NOT NULL DEFAULT 0,
|
|
||||||
created_at INTEGER NOT NULL,
|
|
||||||
updated_at INTEGER NOT NULL
|
|
||||||
)
|
|
||||||
`);
|
|
||||||
|
|
||||||
const columns = await db.execute(`PRAGMA table_info(zen_pins)`);
|
|
||||||
const columnNames = columns.map((row) => row.getResultByName('name'));
|
|
||||||
|
|
||||||
// Helper function to add column if it doesn't exist
|
|
||||||
const addColumnIfNotExists = async (columnName, definition) => {
|
|
||||||
if (!columnNames.includes(columnName)) {
|
|
||||||
await db.execute(`ALTER TABLE zen_pins ADD COLUMN ${columnName} ${definition}`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
await addColumnIfNotExists('edited_title', 'BOOLEAN NOT NULL DEFAULT 0');
|
|
||||||
await addColumnIfNotExists('is_folder_collapsed', 'BOOLEAN NOT NULL DEFAULT 0');
|
|
||||||
await addColumnIfNotExists('folder_icon', 'TEXT DEFAULT NULL');
|
|
||||||
await addColumnIfNotExists('folder_parent_uuid', 'TEXT DEFAULT NULL');
|
|
||||||
|
|
||||||
await db.execute(`
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_zen_pins_uuid ON zen_pins(uuid)
|
|
||||||
`);
|
|
||||||
|
|
||||||
await db.execute(`
|
|
||||||
CREATE TABLE IF NOT EXISTS zen_pins_changes (
|
|
||||||
uuid TEXT PRIMARY KEY,
|
|
||||||
timestamp INTEGER NOT NULL
|
|
||||||
)
|
|
||||||
`);
|
|
||||||
|
|
||||||
await db.execute(`
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_zen_pins_changes_uuid ON zen_pins_changes(uuid)
|
|
||||||
`);
|
|
||||||
|
|
||||||
this._resolveInitialized();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private helper method to notify observers with a list of changed UUIDs.
|
|
||||||
* @param {string} event - The observer event name.
|
|
||||||
* @param {Array<string>} uuids - Array of changed workspace UUIDs.
|
|
||||||
*/
|
|
||||||
_notifyPinsChanged(event, uuids) {
|
|
||||||
if (uuids.length === 0) return; // No changes to notify
|
|
||||||
|
|
||||||
// Convert the array of UUIDs to a JSON string
|
|
||||||
const data = JSON.stringify(uuids);
|
|
||||||
|
|
||||||
Services.obs.notifyObservers(null, event, data);
|
|
||||||
},
|
|
||||||
|
|
||||||
async savePin(pin, notifyObservers = true) {
|
|
||||||
const changedUUIDs = new Set();
|
|
||||||
|
|
||||||
await PlacesUtils.withConnectionWrapper('ZenPinnedTabsStorage.savePin', async (db) => {
|
|
||||||
await db.executeTransaction(async () => {
|
|
||||||
const now = Date.now();
|
|
||||||
|
|
||||||
let newPosition;
|
|
||||||
if ('position' in pin && Number.isFinite(pin.position)) {
|
|
||||||
newPosition = pin.position;
|
|
||||||
} else {
|
|
||||||
// Get the maximum position within the same parent group (or null for root level)
|
|
||||||
const maxPositionResult = await db.execute(
|
|
||||||
`
|
|
||||||
SELECT MAX("position") as max_position
|
|
||||||
FROM zen_pins
|
|
||||||
WHERE COALESCE(folder_parent_uuid, '') = COALESCE(:folder_parent_uuid, '')
|
|
||||||
`,
|
|
||||||
{ folder_parent_uuid: pin.parentUuid || null }
|
|
||||||
);
|
|
||||||
const maxPosition = maxPositionResult[0].getResultByName('max_position') || 0;
|
|
||||||
newPosition = maxPosition + 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert or replace the pin
|
|
||||||
await db.executeCached(
|
|
||||||
`
|
|
||||||
INSERT OR REPLACE INTO zen_pins (
|
|
||||||
uuid, title, url, container_id, workspace_uuid, position,
|
|
||||||
is_essential, is_group, folder_parent_uuid, edited_title, created_at,
|
|
||||||
updated_at, is_folder_collapsed, folder_icon
|
|
||||||
) VALUES (
|
|
||||||
:uuid, :title, :url, :container_id, :workspace_uuid, :position,
|
|
||||||
:is_essential, :is_group, :folder_parent_uuid, :edited_title,
|
|
||||||
COALESCE((SELECT created_at FROM zen_pins WHERE uuid = :uuid), :now),
|
|
||||||
:now, :is_folder_collapsed, :folder_icon
|
|
||||||
)
|
|
||||||
`,
|
|
||||||
{
|
|
||||||
uuid: pin.uuid,
|
|
||||||
title: pin.title,
|
|
||||||
url: pin.isGroup ? '' : pin.url,
|
|
||||||
container_id: pin.containerTabId || null,
|
|
||||||
workspace_uuid: pin.workspaceUuid || null,
|
|
||||||
position: newPosition,
|
|
||||||
is_essential: pin.isEssential || false,
|
|
||||||
is_group: pin.isGroup || false,
|
|
||||||
folder_parent_uuid: pin.parentUuid || null,
|
|
||||||
edited_title: pin.editedTitle || false,
|
|
||||||
now,
|
|
||||||
folder_icon: pin.folderIcon || null,
|
|
||||||
is_folder_collapsed: pin.isFolderCollapsed || false,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
await db.execute(
|
|
||||||
`
|
|
||||||
INSERT OR REPLACE INTO zen_pins_changes (uuid, timestamp)
|
|
||||||
VALUES (:uuid, :timestamp)
|
|
||||||
`,
|
|
||||||
{
|
|
||||||
uuid: pin.uuid,
|
|
||||||
timestamp: Math.floor(now / 1000),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
changedUUIDs.add(pin.uuid);
|
|
||||||
await this.updateLastChangeTimestamp(db);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (notifyObservers) {
|
|
||||||
this._notifyPinsChanged('zen-pin-updated', Array.from(changedUUIDs));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async getPins() {
|
|
||||||
const db = await PlacesUtils.promiseDBConnection();
|
|
||||||
const rows = await db.executeCached(`
|
|
||||||
SELECT * FROM zen_pins
|
|
||||||
ORDER BY position ASC
|
|
||||||
`);
|
|
||||||
return rows.map((row) => ({
|
|
||||||
uuid: row.getResultByName('uuid'),
|
|
||||||
title: row.getResultByName('title'),
|
|
||||||
url: row.getResultByName('url'),
|
|
||||||
containerTabId: row.getResultByName('container_id'),
|
|
||||||
workspaceUuid: row.getResultByName('workspace_uuid'),
|
|
||||||
position: row.getResultByName('position'),
|
|
||||||
isEssential: Boolean(row.getResultByName('is_essential')),
|
|
||||||
isGroup: Boolean(row.getResultByName('is_group')),
|
|
||||||
parentUuid: row.getResultByName('folder_parent_uuid'),
|
|
||||||
editedTitle: Boolean(row.getResultByName('edited_title')),
|
|
||||||
folderIcon: row.getResultByName('folder_icon'),
|
|
||||||
isFolderCollapsed: Boolean(row.getResultByName('is_folder_collapsed')),
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new group
|
|
||||||
* @param {string} title - The title of the group
|
|
||||||
* @param {string} workspaceUuid - The workspace UUID (optional)
|
|
||||||
* @param {string} parentUuid - The parent group UUID (optional, null for root level)
|
|
||||||
* @param {number} position - The position of the group (optional, will auto-calculate if not provided)
|
|
||||||
* @param {boolean} notifyObservers - Whether to notify observers (default: true)
|
|
||||||
* @returns {Promise<string>} The UUID of the created group
|
|
||||||
*/
|
|
||||||
async createGroup(
|
|
||||||
title,
|
|
||||||
icon = null,
|
|
||||||
isCollapsed = false,
|
|
||||||
workspaceUuid = null,
|
|
||||||
parentUuid = null,
|
|
||||||
position = null,
|
|
||||||
notifyObservers = true
|
|
||||||
) {
|
|
||||||
if (!title || typeof title !== 'string') {
|
|
||||||
throw new Error('Group title is required and must be a string');
|
|
||||||
}
|
|
||||||
|
|
||||||
const groupUuid = gZenUIManager.generateUuidv4();
|
|
||||||
|
|
||||||
const groupPin = {
|
|
||||||
uuid: groupUuid,
|
|
||||||
title,
|
|
||||||
folderIcon: icon || null,
|
|
||||||
isFolderCollapsed: isCollapsed || false,
|
|
||||||
workspaceUuid,
|
|
||||||
parentUuid,
|
|
||||||
position,
|
|
||||||
isGroup: true,
|
|
||||||
isEssential: false,
|
|
||||||
editedTitle: true, // Group titles are always considered edited
|
|
||||||
};
|
|
||||||
|
|
||||||
await this.savePin(groupPin, notifyObservers);
|
|
||||||
return groupUuid;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an existing tab/pin to a group
|
|
||||||
* @param {string} tabUuid - The UUID of the tab to add to the group
|
|
||||||
* @param {string} groupUuid - The UUID of the target group
|
|
||||||
* @param {number} position - The position within the group (optional, will append if not provided)
|
|
||||||
* @param {boolean} notifyObservers - Whether to notify observers (default: true)
|
|
||||||
*/
|
|
||||||
async addTabToGroup(tabUuid, groupUuid, position = null, notifyObservers = true) {
|
|
||||||
if (!tabUuid || !groupUuid) {
|
|
||||||
throw new Error('Both tabUuid and groupUuid are required');
|
|
||||||
}
|
|
||||||
|
|
||||||
const changedUUIDs = new Set();
|
|
||||||
|
|
||||||
await PlacesUtils.withConnectionWrapper('ZenPinnedTabsStorage.addTabToGroup', async (db) => {
|
|
||||||
await db.executeTransaction(async () => {
|
|
||||||
// Verify the group exists and is actually a group
|
|
||||||
const groupCheck = await db.execute(
|
|
||||||
`SELECT is_group FROM zen_pins WHERE uuid = :groupUuid`,
|
|
||||||
{ groupUuid }
|
|
||||||
);
|
|
||||||
|
|
||||||
if (groupCheck.length === 0) {
|
|
||||||
throw new Error(`Group with UUID ${groupUuid} does not exist`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!groupCheck[0].getResultByName('is_group')) {
|
|
||||||
throw new Error(`Pin with UUID ${groupUuid} is not a group`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const tabCheck = await db.execute(`SELECT uuid FROM zen_pins WHERE uuid = :tabUuid`, {
|
|
||||||
tabUuid,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (tabCheck.length === 0) {
|
|
||||||
throw new Error(`Tab with UUID ${tabUuid} does not exist`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const now = Date.now();
|
|
||||||
let newPosition;
|
|
||||||
|
|
||||||
if (position !== null && Number.isFinite(position)) {
|
|
||||||
newPosition = position;
|
|
||||||
} else {
|
|
||||||
// Get the maximum position within the group
|
|
||||||
const maxPositionResult = await db.execute(
|
|
||||||
`SELECT MAX("position") as max_position FROM zen_pins WHERE folder_parent_uuid = :groupUuid`,
|
|
||||||
{ groupUuid }
|
|
||||||
);
|
|
||||||
const maxPosition = maxPositionResult[0].getResultByName('max_position') || 0;
|
|
||||||
newPosition = maxPosition + 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
await db.execute(
|
|
||||||
`
|
|
||||||
UPDATE zen_pins
|
|
||||||
SET folder_parent_uuid = :groupUuid,
|
|
||||||
position = :newPosition,
|
|
||||||
updated_at = :now
|
|
||||||
WHERE uuid = :tabUuid
|
|
||||||
`,
|
|
||||||
{
|
|
||||||
tabUuid,
|
|
||||||
groupUuid,
|
|
||||||
newPosition,
|
|
||||||
now,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
changedUUIDs.add(tabUuid);
|
|
||||||
|
|
||||||
await db.execute(
|
|
||||||
`
|
|
||||||
INSERT OR REPLACE INTO zen_pins_changes (uuid, timestamp)
|
|
||||||
VALUES (:uuid, :timestamp)
|
|
||||||
`,
|
|
||||||
{
|
|
||||||
uuid: tabUuid,
|
|
||||||
timestamp: Math.floor(now / 1000),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
await this.updateLastChangeTimestamp(db);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (notifyObservers) {
|
|
||||||
this._notifyPinsChanged('zen-pin-updated', Array.from(changedUUIDs));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a tab from its group (move to root level)
|
|
||||||
* @param {string} tabUuid - The UUID of the tab to remove from its group
|
|
||||||
* @param {number} newPosition - The new position at root level (optional, will append if not provided)
|
|
||||||
* @param {boolean} notifyObservers - Whether to notify observers (default: true)
|
|
||||||
*/
|
|
||||||
async removeTabFromGroup(tabUuid, newPosition = null, notifyObservers = true) {
|
|
||||||
if (!tabUuid) {
|
|
||||||
throw new Error('tabUuid is required');
|
|
||||||
}
|
|
||||||
|
|
||||||
const changedUUIDs = new Set();
|
|
||||||
|
|
||||||
await PlacesUtils.withConnectionWrapper(
|
|
||||||
'ZenPinnedTabsStorage.removeTabFromGroup',
|
|
||||||
async (db) => {
|
|
||||||
await db.executeTransaction(async () => {
|
|
||||||
// Verify the tab exists and is in a group
|
|
||||||
const tabCheck = await db.execute(
|
|
||||||
`SELECT folder_parent_uuid FROM zen_pins WHERE uuid = :tabUuid`,
|
|
||||||
{ tabUuid }
|
|
||||||
);
|
|
||||||
|
|
||||||
if (tabCheck.length === 0) {
|
|
||||||
throw new Error(`Tab with UUID ${tabUuid} does not exist`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tabCheck[0].getResultByName('folder_parent_uuid')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const now = Date.now();
|
|
||||||
let finalPosition;
|
|
||||||
|
|
||||||
if (newPosition !== null && Number.isFinite(newPosition)) {
|
|
||||||
finalPosition = newPosition;
|
|
||||||
} else {
|
|
||||||
// Get the maximum position at root level (where folder_parent_uuid is null)
|
|
||||||
const maxPositionResult = await db.execute(
|
|
||||||
`SELECT MAX("position") as max_position FROM zen_pins WHERE folder_parent_uuid IS NULL`
|
|
||||||
);
|
|
||||||
const maxPosition = maxPositionResult[0].getResultByName('max_position') || 0;
|
|
||||||
finalPosition = maxPosition + 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the tab to be at root level
|
|
||||||
await db.execute(
|
|
||||||
`
|
|
||||||
UPDATE zen_pins
|
|
||||||
SET folder_parent_uuid = NULL,
|
|
||||||
position = :newPosition,
|
|
||||||
updated_at = :now
|
|
||||||
WHERE uuid = :tabUuid
|
|
||||||
`,
|
|
||||||
{
|
|
||||||
tabUuid,
|
|
||||||
newPosition: finalPosition,
|
|
||||||
now,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
changedUUIDs.add(tabUuid);
|
|
||||||
|
|
||||||
// Record the change
|
|
||||||
await db.execute(
|
|
||||||
`
|
|
||||||
INSERT OR REPLACE INTO zen_pins_changes (uuid, timestamp)
|
|
||||||
VALUES (:uuid, :timestamp)
|
|
||||||
`,
|
|
||||||
{
|
|
||||||
uuid: tabUuid,
|
|
||||||
timestamp: Math.floor(now / 1000),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
await this.updateLastChangeTimestamp(db);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (notifyObservers) {
|
|
||||||
this._notifyPinsChanged('zen-pin-updated', Array.from(changedUUIDs));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async removePin(uuid, notifyObservers = true) {
|
|
||||||
const changedUUIDs = [uuid];
|
|
||||||
|
|
||||||
await PlacesUtils.withConnectionWrapper('ZenPinnedTabsStorage.removePin', async (db) => {
|
|
||||||
await db.executeTransaction(async () => {
|
|
||||||
// Get all child UUIDs first for change tracking
|
|
||||||
const children = await db.execute(
|
|
||||||
`SELECT uuid FROM zen_pins WHERE folder_parent_uuid = :uuid`,
|
|
||||||
{
|
|
||||||
uuid,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add child UUIDs to changedUUIDs array
|
|
||||||
for (const child of children) {
|
|
||||||
changedUUIDs.push(child.getResultByName('uuid'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete the pin/group itself
|
|
||||||
await db.execute(`DELETE FROM zen_pins WHERE uuid = :uuid`, { uuid });
|
|
||||||
|
|
||||||
// Record the changes
|
|
||||||
const now = Math.floor(Date.now() / 1000);
|
|
||||||
for (const changedUuid of changedUUIDs) {
|
|
||||||
await db.execute(
|
|
||||||
`
|
|
||||||
INSERT OR REPLACE INTO zen_pins_changes (uuid, timestamp)
|
|
||||||
VALUES (:uuid, :timestamp)
|
|
||||||
`,
|
|
||||||
{
|
|
||||||
uuid: changedUuid,
|
|
||||||
timestamp: now,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.updateLastChangeTimestamp(db);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (notifyObservers) {
|
|
||||||
this._notifyPinsChanged('zen-pin-removed', changedUUIDs);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async wipeAllPins() {
|
|
||||||
await PlacesUtils.withConnectionWrapper('ZenPinnedTabsStorage.wipeAllPins', async (db) => {
|
|
||||||
await db.execute(`DELETE FROM zen_pins`);
|
|
||||||
await db.execute(`DELETE FROM zen_pins_changes`);
|
|
||||||
await this.updateLastChangeTimestamp(db);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
async markChanged(uuid) {
|
|
||||||
await PlacesUtils.withConnectionWrapper('ZenPinnedTabsStorage.markChanged', async (db) => {
|
|
||||||
const now = Date.now();
|
|
||||||
await db.execute(
|
|
||||||
`
|
|
||||||
INSERT OR REPLACE INTO zen_pins_changes (uuid, timestamp)
|
|
||||||
VALUES (:uuid, :timestamp)
|
|
||||||
`,
|
|
||||||
{
|
|
||||||
uuid,
|
|
||||||
timestamp: Math.floor(now / 1000),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
async getChangedIDs() {
|
|
||||||
const db = await PlacesUtils.promiseDBConnection();
|
|
||||||
const rows = await db.execute(`
|
|
||||||
SELECT uuid, timestamp FROM zen_pins_changes
|
|
||||||
`);
|
|
||||||
const changes = {};
|
|
||||||
for (const row of rows) {
|
|
||||||
changes[row.getResultByName('uuid')] = row.getResultByName('timestamp');
|
|
||||||
}
|
|
||||||
return changes;
|
|
||||||
},
|
|
||||||
|
|
||||||
async clearChangedIDs() {
|
|
||||||
await PlacesUtils.withConnectionWrapper('ZenPinnedTabsStorage.clearChangedIDs', async (db) => {
|
|
||||||
await db.execute(`DELETE FROM zen_pins_changes`);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
shouldReorderPins(before, current, after) {
|
|
||||||
const minGap = 1; // Minimum allowed gap between positions
|
|
||||||
return (
|
|
||||||
(before !== null && current - before < minGap) || (after !== null && after - current < minGap)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
async reorderAllPins(db, changedUUIDs) {
|
|
||||||
const pins = await db.execute(`
|
|
||||||
SELECT uuid
|
|
||||||
FROM zen_pins
|
|
||||||
ORDER BY position ASC
|
|
||||||
`);
|
|
||||||
|
|
||||||
for (let i = 0; i < pins.length; i++) {
|
|
||||||
const newPosition = (i + 1) * 1000; // Use large increments
|
|
||||||
await db.execute(
|
|
||||||
`
|
|
||||||
UPDATE zen_pins
|
|
||||||
SET position = :newPosition
|
|
||||||
WHERE uuid = :uuid
|
|
||||||
`,
|
|
||||||
{ newPosition, uuid: pins[i].getResultByName('uuid') }
|
|
||||||
);
|
|
||||||
changedUUIDs.add(pins[i].getResultByName('uuid'));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async updateLastChangeTimestamp(db) {
|
|
||||||
const now = Date.now();
|
|
||||||
await db.execute(
|
|
||||||
`
|
|
||||||
INSERT OR REPLACE INTO moz_meta (key, value)
|
|
||||||
VALUES ('zen_pins_last_change', :now)
|
|
||||||
`,
|
|
||||||
{ now }
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
async getLastChangeTimestamp() {
|
|
||||||
const db = await PlacesUtils.promiseDBConnection();
|
|
||||||
const result = await db.executeCached(`
|
|
||||||
SELECT value FROM moz_meta WHERE key = 'zen_pins_last_change'
|
|
||||||
`);
|
|
||||||
return result.length ? parseInt(result[0].getResultByName('value'), 10) : 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
async updatePinPositions(pins) {
|
|
||||||
const changedUUIDs = new Set();
|
|
||||||
|
|
||||||
await PlacesUtils.withConnectionWrapper(
|
|
||||||
'ZenPinnedTabsStorage.updatePinPositions',
|
|
||||||
async (db) => {
|
|
||||||
await db.executeTransaction(async () => {
|
|
||||||
const now = Date.now();
|
|
||||||
|
|
||||||
for (let i = 0; i < pins.length; i++) {
|
|
||||||
const pin = pins[i];
|
|
||||||
const newPosition = (i + 1) * 1000;
|
|
||||||
|
|
||||||
await db.execute(
|
|
||||||
`
|
|
||||||
UPDATE zen_pins
|
|
||||||
SET position = :newPosition
|
|
||||||
WHERE uuid = :uuid
|
|
||||||
`,
|
|
||||||
{ newPosition, uuid: pin.uuid }
|
|
||||||
);
|
|
||||||
|
|
||||||
changedUUIDs.add(pin.uuid);
|
|
||||||
|
|
||||||
// Record the change
|
|
||||||
await db.execute(
|
|
||||||
`
|
|
||||||
INSERT OR REPLACE INTO zen_pins_changes (uuid, timestamp)
|
|
||||||
VALUES (:uuid, :timestamp)
|
|
||||||
`,
|
|
||||||
{
|
|
||||||
uuid: pin.uuid,
|
|
||||||
timestamp: Math.floor(now / 1000),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.updateLastChangeTimestamp(db);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
this._notifyPinsChanged('zen-pin-updated', Array.from(changedUUIDs));
|
|
||||||
},
|
|
||||||
|
|
||||||
async updatePinTitle(uuid, newTitle, isEdited = true, notifyObservers = true) {
|
|
||||||
if (!uuid || typeof newTitle !== 'string') {
|
|
||||||
throw new Error('Invalid parameters: uuid and newTitle are required');
|
|
||||||
}
|
|
||||||
|
|
||||||
const changedUUIDs = new Set();
|
|
||||||
|
|
||||||
await PlacesUtils.withConnectionWrapper('ZenPinnedTabsStorage.updatePinTitle', async (db) => {
|
|
||||||
await db.executeTransaction(async () => {
|
|
||||||
const now = Date.now();
|
|
||||||
|
|
||||||
// Update the pin's title and edited_title flag
|
|
||||||
const result = await db.execute(
|
|
||||||
`
|
|
||||||
UPDATE zen_pins
|
|
||||||
SET title = :newTitle,
|
|
||||||
edited_title = :isEdited,
|
|
||||||
updated_at = :now
|
|
||||||
WHERE uuid = :uuid
|
|
||||||
`,
|
|
||||||
{
|
|
||||||
uuid,
|
|
||||||
newTitle,
|
|
||||||
isEdited,
|
|
||||||
now,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Only proceed with change tracking if a row was actually updated
|
|
||||||
if (result.rowsAffected > 0) {
|
|
||||||
changedUUIDs.add(uuid);
|
|
||||||
|
|
||||||
// Record the change
|
|
||||||
await db.execute(
|
|
||||||
`
|
|
||||||
INSERT OR REPLACE INTO zen_pins_changes (uuid, timestamp)
|
|
||||||
VALUES (:uuid, :timestamp)
|
|
||||||
`,
|
|
||||||
{
|
|
||||||
uuid,
|
|
||||||
timestamp: Math.floor(now / 1000),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
await this.updateLastChangeTimestamp(db);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (notifyObservers && changedUUIDs.size > 0) {
|
|
||||||
this._notifyPinsChanged('zen-pin-updated', Array.from(changedUUIDs));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async __dropTables() {
|
|
||||||
await PlacesUtils.withConnectionWrapper('ZenPinnedTabsStorage.__dropTables', async (db) => {
|
|
||||||
await db.execute(`DROP TABLE IF EXISTS zen_pins`);
|
|
||||||
await db.execute(`DROP TABLE IF EXISTS zen_pins_changes`);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
ZenPinnedTabsStorage.promiseInitialized = new Promise((resolve) => {
|
|
||||||
ZenPinnedTabsStorage._resolveInitialized = resolve;
|
|
||||||
ZenPinnedTabsStorage.init();
|
|
||||||
});
|
|
||||||
@@ -52,7 +52,6 @@ export class nsZenSiteDataPanel {
|
|||||||
this.panel.addEventListener('popupshowing', this);
|
this.panel.addEventListener('popupshowing', this);
|
||||||
this.document.getElementById('zen-site-data-manage-addons').addEventListener('click', this);
|
this.document.getElementById('zen-site-data-manage-addons').addEventListener('click', this);
|
||||||
this.document.getElementById('zen-site-data-settings-more').addEventListener('click', this);
|
this.document.getElementById('zen-site-data-settings-more').addEventListener('click', this);
|
||||||
this.anchor.addEventListener('click', this);
|
|
||||||
const kCommandIDs = [
|
const kCommandIDs = [
|
||||||
'zen-site-data-header-share',
|
'zen-site-data-header-share',
|
||||||
'zen-site-data-header-bookmark',
|
'zen-site-data-header-bookmark',
|
||||||
@@ -140,12 +139,6 @@ export class nsZenSiteDataPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get #currentPageIsBookmarked() {
|
|
||||||
// A hacky way to check if the current page is bookmarked, but
|
|
||||||
// it works for our purposes.
|
|
||||||
return this.window.BookmarkingUI.star?.hasAttribute('starred');
|
|
||||||
}
|
|
||||||
|
|
||||||
#setSiteHeader() {
|
#setSiteHeader() {
|
||||||
{
|
{
|
||||||
const button = this.document.getElementById('zen-site-data-header-reader-mode');
|
const button = this.document.getElementById('zen-site-data-header-reader-mode');
|
||||||
@@ -163,7 +156,7 @@ export class nsZenSiteDataPanel {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
const button = this.document.getElementById('zen-site-data-header-bookmark');
|
const button = this.document.getElementById('zen-site-data-header-bookmark');
|
||||||
const isPageBookmarked = this.#currentPageIsBookmarked;
|
const isPageBookmarked = this.window.BookmarkingUI.star?.hasAttribute('starred');
|
||||||
|
|
||||||
if (isPageBookmarked) {
|
if (isPageBookmarked) {
|
||||||
button.classList.add('active');
|
button.classList.add('active');
|
||||||
@@ -555,10 +548,6 @@ export class nsZenSiteDataPanel {
|
|||||||
BrowserCommands.pageInfo(null, 'permTab');
|
BrowserCommands.pageInfo(null, 'permTab');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'zen-site-data-icon-button': {
|
|
||||||
this.window.gUnifiedExtensions.togglePanel(event);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
default: {
|
||||||
const item = event.target.closest('.permission-popup-permission-item');
|
const item = event.target.closest('.permission-popup-permission-item');
|
||||||
if (!item) {
|
if (!item) {
|
||||||
|
|||||||
308
src/zen/workspaces/ZenWindowSyncing.mjs
Normal file
308
src/zen/workspaces/ZenWindowSyncing.mjs
Normal file
@@ -0,0 +1,308 @@
|
|||||||
|
// 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 nsZenWorkspaceWindowSync extends nsZenMultiWindowFeature {
|
||||||
|
#ignoreNextEvents = false;
|
||||||
|
#waitForPromise = null;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
if (!window.closed) {
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async init() {
|
||||||
|
await gZenWorkspaces.promiseInitialized;
|
||||||
|
this.#makeSureAllTabsHaveIds();
|
||||||
|
this.#setUpEventListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
#makeSureAllTabsHaveIds() {
|
||||||
|
const allTabs = gZenWorkspaces.allStoredTabs;
|
||||||
|
for (const tab of allTabs) {
|
||||||
|
if (!tab.hasAttribute('zen-sync-id') && !tab.hasAttribute('zen-empty-tab')) {
|
||||||
|
const tabId = gZenUIManager.generateUuidv4();
|
||||||
|
tab.setAttribute('zen-sync-id', tabId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#setUpEventListeners() {
|
||||||
|
const kEvents = [
|
||||||
|
'TabClose',
|
||||||
|
'TabOpen',
|
||||||
|
'TabMove',
|
||||||
|
|
||||||
|
'TabPinned',
|
||||||
|
'TabUnpinned',
|
||||||
|
|
||||||
|
'TabAddedToEssentials',
|
||||||
|
'TabRemovedFromEssentials',
|
||||||
|
|
||||||
|
'TabHide',
|
||||||
|
'TabShow',
|
||||||
|
|
||||||
|
'ZenTabIconChanged',
|
||||||
|
'ZenTabLabelChanged',
|
||||||
|
|
||||||
|
'TabGroupCreate',
|
||||||
|
'TabGroupRemoved',
|
||||||
|
'TabGrouped',
|
||||||
|
'TabUngrouped',
|
||||||
|
'TabGroupMoved',
|
||||||
|
];
|
||||||
|
const eventListener = this.#handleEvent.bind(this);
|
||||||
|
for (const event of kEvents) {
|
||||||
|
window.addEventListener(event, eventListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('unload', () => {
|
||||||
|
for (const event of kEvents) {
|
||||||
|
window.removeEventListener(event, eventListener);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#handleEvent(event) {
|
||||||
|
this.#propagateToOtherWindows(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
async #propagateToOtherWindows(event) {
|
||||||
|
if (this.#ignoreNextEvents) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.#waitForPromise) {
|
||||||
|
await this.#waitForPromise;
|
||||||
|
}
|
||||||
|
this.#waitForPromise = new Promise((resolve) => {
|
||||||
|
this.foreachWindowAsActive(async (browser) => {
|
||||||
|
if (browser.gZenWorkspaceWindowSync && !this.windowIsActive(browser)) {
|
||||||
|
await browser.gZenWorkspaceWindowSync.onExternalTabEvent(event);
|
||||||
|
}
|
||||||
|
}).then(() => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async onExternalTabEvent(event) {
|
||||||
|
this.#ignoreNextEvents = true;
|
||||||
|
switch (event.type) {
|
||||||
|
case 'TabClose':
|
||||||
|
this.#onTabClose(event);
|
||||||
|
break;
|
||||||
|
case 'TabOpen':
|
||||||
|
await this.#onTabOpen(event);
|
||||||
|
break;
|
||||||
|
case 'TabPinned':
|
||||||
|
this.#onTabPinned(event);
|
||||||
|
break;
|
||||||
|
case 'TabUnpinned':
|
||||||
|
this.#onTabUnpinned(event);
|
||||||
|
break;
|
||||||
|
case 'TabAddedToEssentials':
|
||||||
|
this.#onTabAddedToEssentials(event);
|
||||||
|
break;
|
||||||
|
case 'TabRemovedFromEssentials':
|
||||||
|
this.#onTabRemovedFromEssentials(event);
|
||||||
|
break;
|
||||||
|
case 'TabHide':
|
||||||
|
this.#onTabHide(event);
|
||||||
|
break;
|
||||||
|
case 'TabShow':
|
||||||
|
this.#onTabShow(event);
|
||||||
|
break;
|
||||||
|
case 'TabMove':
|
||||||
|
case 'TabGroupMoved':
|
||||||
|
this.#onTabMove(event);
|
||||||
|
break;
|
||||||
|
case 'ZenTabIconChanged':
|
||||||
|
this.#onTabIconChanged(event);
|
||||||
|
break;
|
||||||
|
case 'ZenTabLabelChanged':
|
||||||
|
this.#onTabLabelChanged(event);
|
||||||
|
break;
|
||||||
|
case 'TabGroupCreate':
|
||||||
|
this.#onTabGroupCreate(event);
|
||||||
|
break;
|
||||||
|
case 'TabGroupRemoved':
|
||||||
|
case 'TabGrouped':
|
||||||
|
case 'TabUngrouped':
|
||||||
|
// Tab grouping changes are automatically synced by Firefox
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.warn(`Unhandled event type: ${event.type}`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.#ignoreNextEvents = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#getTabId(tab) {
|
||||||
|
return tab.getAttribute('zen-sync-id');
|
||||||
|
}
|
||||||
|
|
||||||
|
#getTabWithId(tabId) {
|
||||||
|
for (const tab of gZenWorkspaces.allStoredTabs) {
|
||||||
|
if (this.#getTabId(tab) === tabId) {
|
||||||
|
return tab;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabClose(event) {
|
||||||
|
const targetTab = event.target;
|
||||||
|
const tabId = this.#getTabId(targetTab);
|
||||||
|
const tabToClose = this.#getTabWithId(tabId);
|
||||||
|
if (tabToClose) {
|
||||||
|
gBrowser.removeTab(tabToClose);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabPinned(event) {
|
||||||
|
const targetTab = event.target;
|
||||||
|
if (targetTab.hasAttribute('zen-essential')) {
|
||||||
|
return this.#onTabAddedToEssentials(event);
|
||||||
|
}
|
||||||
|
const tabId = this.#getTabId(targetTab);
|
||||||
|
const elementIndex = targetTab.elementIndex;
|
||||||
|
const tabToPin = this.#getTabWithId(tabId);
|
||||||
|
if (tabToPin) {
|
||||||
|
gBrowser.pinTab(tabToPin);
|
||||||
|
gBrowser.moveTabTo(tabToPin, { elementIndex, forceUngrouped: !!targetTab.group });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabUnpinned(event) {
|
||||||
|
const targetTab = event.target;
|
||||||
|
const tabId = this.#getTabId(targetTab);
|
||||||
|
const tabToUnpin = this.#getTabWithId(tabId);
|
||||||
|
if (tabToUnpin) {
|
||||||
|
gBrowser.unpinTab(tabToUnpin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabIconChanged(event) {
|
||||||
|
this.#updateTabIconAndLabel(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabLabelChanged(event) {
|
||||||
|
this.#updateTabIconAndLabel(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
#updateTabIconAndLabel(event) {
|
||||||
|
const targetTab = event.target;
|
||||||
|
const tabId = this.#getTabId(targetTab);
|
||||||
|
const tabToChange = this.#getTabWithId(tabId);
|
||||||
|
if (tabToChange && tabToChange.hasAttribute('pending')) {
|
||||||
|
gBrowser.setIcon(tabToChange, gBrowser.getIcon(targetTab));
|
||||||
|
gBrowser._setTabLabel(tabToChange, targetTab.label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabAddedToEssentials(event) {
|
||||||
|
const targetTab = event.target;
|
||||||
|
const tabId = this.#getTabId(targetTab);
|
||||||
|
const tabToAdd = this.#getTabWithId(tabId);
|
||||||
|
if (tabToAdd) {
|
||||||
|
gZenPinnedTabManager.addToEssentials(tabToAdd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabRemovedFromEssentials(event) {
|
||||||
|
const targetTab = event.target;
|
||||||
|
const tabId = this.#getTabId(targetTab);
|
||||||
|
const tabToRemove = this.#getTabWithId(tabId);
|
||||||
|
if (tabToRemove) {
|
||||||
|
gZenPinnedTabManager.removeFromEssentials(tabToRemove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabHide(event) {
|
||||||
|
const targetTab = event.target;
|
||||||
|
const tabId = this.#getTabId(targetTab);
|
||||||
|
const tabToHide = this.#getTabWithId(tabId);
|
||||||
|
if (tabToHide) {
|
||||||
|
gBrowser.hideTab(tabToHide);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabShow(event) {
|
||||||
|
const targetTab = event.target;
|
||||||
|
const tabId = this.#getTabId(targetTab);
|
||||||
|
const tabToShow = this.#getTabWithId(tabId);
|
||||||
|
if (tabToShow) {
|
||||||
|
gBrowser.showTab(tabToShow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabMove(event) {
|
||||||
|
const targetTab = event.target;
|
||||||
|
const tabId = this.#getTabId(targetTab);
|
||||||
|
const tabToMove = this.#getTabWithId(tabId);
|
||||||
|
const workspaceId = targetTab.getAttribute('zen-workspace-id');
|
||||||
|
const isEssential = targetTab.hasAttribute('zen-essential');
|
||||||
|
if (tabToMove) {
|
||||||
|
let tabSibling = targetTab.previousElementSibling;
|
||||||
|
let isFirst = false;
|
||||||
|
if (!tabSibling?.hasAttribute('zen-sync-id')) {
|
||||||
|
isFirst = true;
|
||||||
|
}
|
||||||
|
gBrowser.zenHandleTabMove(tabToMove, () => {
|
||||||
|
if (isFirst) {
|
||||||
|
let container;
|
||||||
|
if (isEssential) {
|
||||||
|
container = gZenWorkspaces.getEssentialsSection(tabToMove);
|
||||||
|
} else {
|
||||||
|
const workspaceElement = gZenWorkspaces.workspaceElement(workspaceId);
|
||||||
|
container = tabToMove.pinned
|
||||||
|
? workspaceElement.pinnedTabsContainer
|
||||||
|
: workspaceElement.tabsContainer;
|
||||||
|
}
|
||||||
|
container.insertBefore(tabToMove, container.firstChild);
|
||||||
|
} else {
|
||||||
|
let relativeTab = gZenWorkspaces.allStoredTabs.find((tab) => {
|
||||||
|
return this.#getTabId(tab) === this.#getTabId(tabSibling);
|
||||||
|
});
|
||||||
|
if (relativeTab) {
|
||||||
|
relativeTab.after(tabToMove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async #onTabOpen(event) {
|
||||||
|
const targetTab = event.target;
|
||||||
|
const isPinned = targetTab.pinned;
|
||||||
|
const isEssential = isPinned && targetTab.hasAttribute('zen-essential');
|
||||||
|
if (!this.#getTabId(targetTab) && !targetTab.hasAttribute('zen-empty-tab')) {
|
||||||
|
const tabId = gZenUIManager.generateUuidv4();
|
||||||
|
targetTab.setAttribute('zen-sync-id', tabId);
|
||||||
|
}
|
||||||
|
const duplicatedTab = gBrowser.addTrustedTab(targetTab.linkedBrowser.currentURI.spec, {
|
||||||
|
createLazyBrowser: true,
|
||||||
|
essential: isEssential,
|
||||||
|
pinned: isPinned,
|
||||||
|
});
|
||||||
|
if (!isEssential) {
|
||||||
|
gZenWorkspaces.moveTabToWorkspace(
|
||||||
|
duplicatedTab,
|
||||||
|
targetTab.getAttribute('zen-workspace-id')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
duplicatedTab.setAttribute('zen-sync-id', targetTab.getAttribute('zen-sync-id'));
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabGroupCreate(event) {
|
||||||
|
void event;
|
||||||
|
//const targetGroup = event.target;
|
||||||
|
//const isSplitView = targetGroup.classList.contains('zen-split-view');
|
||||||
|
//const isFolder = targetGroup.isZenFolder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.gZenWorkspaceWindowSync = new nsZenWorkspaceWindowSync();
|
||||||
|
}
|
||||||
@@ -932,7 +932,6 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature {
|
|||||||
await this.workspaceBookmarks();
|
await this.workspaceBookmarks();
|
||||||
await this.initializeTabsStripSections();
|
await this.initializeTabsStripSections();
|
||||||
this._initializeEmptyTab();
|
this._initializeEmptyTab();
|
||||||
await gZenPinnedTabManager.refreshPinnedTabs({ init: true });
|
|
||||||
await this.changeWorkspace(activeWorkspace, { onInit: true });
|
await this.changeWorkspace(activeWorkspace, { onInit: true });
|
||||||
this.#fixTabPositions();
|
this.#fixTabPositions();
|
||||||
this.onWindowResize();
|
this.onWindowResize();
|
||||||
@@ -1471,11 +1470,6 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature {
|
|||||||
!tab.hasAttribute('zen-empty-tab') &&
|
!tab.hasAttribute('zen-empty-tab') &&
|
||||||
!tab.hasAttribute('zen-essential')
|
!tab.hasAttribute('zen-essential')
|
||||||
);
|
);
|
||||||
for (const tab of tabs) {
|
|
||||||
if (tab.pinned) {
|
|
||||||
await ZenPinnedTabsStorage.removePin(tab.getAttribute('zen-pin-id'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gBrowser.removeTabs(tabs, {
|
gBrowser.removeTabs(tabs, {
|
||||||
animate: false,
|
animate: false,
|
||||||
skipSessionStore: true,
|
skipSessionStore: true,
|
||||||
@@ -2502,7 +2496,7 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature {
|
|||||||
}
|
}
|
||||||
// Only animate if it's from an event
|
// Only animate if it's from an event
|
||||||
let animateContainer = target && target.target instanceof EventTarget;
|
let animateContainer = target && target.target instanceof EventTarget;
|
||||||
if (target?.type === 'TabClose' || target?.type === 'TabOpen') {
|
if (target?.type === 'TabClose' || target?.type === 'TabOpened') {
|
||||||
animateContainer = target.target.pinned;
|
animateContainer = target.target.pinned;
|
||||||
}
|
}
|
||||||
await this.onPinnedTabsResize(
|
await this.onPinnedTabsResize(
|
||||||
@@ -2514,29 +2508,14 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateShouldHideSeparator(arrowScrollbox, pinnedContainer, fromTabSelection = false) {
|
updateShouldHideSeparator(arrowScrollbox, pinnedContainer) {
|
||||||
const visibleTabsFound = () => {
|
|
||||||
let count = 0;
|
|
||||||
for (const child of arrowScrollbox.children) {
|
|
||||||
if (
|
|
||||||
!child.hasAttribute('hidden') &&
|
|
||||||
!child.closing &&
|
|
||||||
!child.hasAttribute('zen-empty-tab')
|
|
||||||
) {
|
|
||||||
count++;
|
|
||||||
if (count > 1) {
|
|
||||||
// Early return
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// <= 2 because we have the empty tab and the new tab button
|
// <= 2 because we have the empty tab and the new tab button
|
||||||
const shouldHideSeparator = fromTabSelection
|
const shouldHideSeparator =
|
||||||
? pinnedContainer.hasAttribute('hide-separator')
|
pinnedContainer.children.length === 1 ||
|
||||||
: pinnedContainer.children.length === 1 || !visibleTabsFound();
|
Array.from(arrowScrollbox.children).filter(
|
||||||
|
(child) =>
|
||||||
|
!child.hasAttribute('hidden') && !child.closing && !child.hasAttribute('zen-empty-tab')
|
||||||
|
).length <= 1;
|
||||||
if (shouldHideSeparator) {
|
if (shouldHideSeparator) {
|
||||||
pinnedContainer.setAttribute('hide-separator', 'true');
|
pinnedContainer.setAttribute('hide-separator', 'true');
|
||||||
} else {
|
} else {
|
||||||
@@ -2671,7 +2650,7 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature {
|
|||||||
}
|
}
|
||||||
const workspaceID = tab.getAttribute('zen-workspace-id');
|
const workspaceID = tab.getAttribute('zen-workspace-id');
|
||||||
const isEssential = tab.getAttribute('zen-essential') === 'true';
|
const isEssential = tab.getAttribute('zen-essential') === 'true';
|
||||||
this.updateShouldHideSeparator(this.activeWorkspaceStrip, this.pinnedTabsContainer, true);
|
|
||||||
if (tab.hasAttribute('zen-empty-tab')) {
|
if (tab.hasAttribute('zen-empty-tab')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ export default [
|
|||||||
'ZenWorkspaceBookmarksStorage',
|
'ZenWorkspaceBookmarksStorage',
|
||||||
|
|
||||||
'gZenPinnedTabManager',
|
'gZenPinnedTabManager',
|
||||||
'ZenPinnedTabsStorage',
|
|
||||||
|
|
||||||
'gZenEmojiPicker',
|
'gZenEmojiPicker',
|
||||||
'gZenSessionStore',
|
'gZenSessionStore',
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
"brandShortName": "Zen",
|
"brandShortName": "Zen",
|
||||||
"brandFullName": "Zen Browser",
|
"brandFullName": "Zen Browser",
|
||||||
"release": {
|
"release": {
|
||||||
"displayVersion": "1.17.6b",
|
"displayVersion": "1.17.4b",
|
||||||
"github": {
|
"github": {
|
||||||
"repo": "zen-browser/desktop"
|
"repo": "zen-browser/desktop"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user