From 78077fab9dc984882c9730feb85cfc7c721dbb35 Mon Sep 17 00:00:00 2001 From: windingwind <33902321+windingwind@users.noreply.github.com> Date: Thu, 12 Sep 2024 12:26:31 +0200 Subject: [PATCH] Fix main window layout and window resizing (#4676) - Replace flex attribute with flex-shrink and flex-grow style to allow elements to be resized by splitter and window resizing. - Set the max-width on collections pane to prevent it from pushing other panes outside window border - Set the min-width on window according to the size of both library and reader tabs - Use stacked layout when window width is small fix: #4669 --- chrome/content/zotero/contextPane.js | 28 +++++----- chrome/content/zotero/zoteroPane.js | 75 +++++++++++++++++++------- chrome/content/zotero/zoteroPane.xhtml | 14 ++--- chrome/skin/default/zotero/overlay.css | 22 -------- scss/components/_collection-tree.scss | 4 +- scss/components/_contextPane.scss | 4 ++ scss/components/_item-tree.scss | 2 + scss/components/_mainWindow.scss | 28 +++++++++- scss/components/_toolbar.scss | 6 +++ scss/elements/_itemPane.scss | 4 +- 10 files changed, 125 insertions(+), 62 deletions(-) diff --git a/chrome/content/zotero/contextPane.js b/chrome/content/zotero/contextPane.js index 6eea8c82a8..2cc4876b38 100644 --- a/chrome/content/zotero/contextPane.js +++ b/chrome/content/zotero/contextPane.js @@ -48,6 +48,19 @@ var ZoteroContextPane = new function () { : _contextPaneSplitter) }); + Object.defineProperty(this, 'collapsed', { + get: () => { + return this.splitter.getAttribute('state') === 'collapsed'; + }, + set: (collapsed) => { + _contextPane.setAttribute('collapsed', !!collapsed); + _contextPaneInner.setAttribute('collapsed', !!collapsed); + _contextPaneSplitter.setAttribute('state', collapsed ? 'collapsed' : 'open'); + _contextPaneSplitterStacked.setAttribute('state', collapsed ? 'collapsed' : 'open'); + _update(); + } + }); + this.update = _update; this.focus = () => { @@ -132,7 +145,6 @@ var ZoteroContextPane = new function () { } if (_isStacked()) { _contextPaneSplitterStacked.setAttribute('hidden', false); - _contextPaneSplitter.setAttribute('state', 'open'); _contextPaneSplitter.setAttribute('hidden', true); _contextPane.classList.add('stacked'); _contextPane.classList.remove('standard'); @@ -149,7 +161,6 @@ var ZoteroContextPane = new function () { else { _contextPaneSplitter.setAttribute('hidden', false); _contextPaneSplitterStacked.setAttribute('hidden', true); - _contextPaneSplitterStacked.setAttribute('state', 'open'); _contextPane.classList.add('standard'); _contextPane.classList.remove('stacked'); _readerSidenav.classList.remove('stacked'); @@ -176,6 +187,8 @@ var ZoteroContextPane = new function () { _updatePaneWidth(); _updateAddToNote(); + + ZoteroPane.updateLayoutConstraints(); } function _isLibraryReadOnly(libraryID) { @@ -183,15 +196,6 @@ var ZoteroContextPane = new function () { } function _togglePane() { - var splitter = ZoteroContextPane.splitter; - - var open = true; - if (splitter.getAttribute('state') != 'collapsed') { - open = false; - } - - _contextPane.setAttribute('collapsed', !open); - splitter.setAttribute('state', open ? 'open' : 'collapsed'); - _update(); + this.collapsed = !this.collapsed; } }; diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js index 17c59252d6..7c09abd955 100644 --- a/chrome/content/zotero/zoteroPane.js +++ b/chrome/content/zotero/zoteroPane.js @@ -6248,8 +6248,7 @@ var ZoteroPane = new function() */ this.unserializePersist = function () { _unserialized = true; - var serializedValues = Zotero.Prefs.get("pane.persist"); - if (!serializedValues) return; + var serializedValues = Zotero.Prefs.get("pane.persist") || "{}"; serializedValues = JSON.parse(serializedValues); for (var id in serializedValues) { @@ -6354,33 +6353,73 @@ var ZoteroPane = new function() var itemsPaneContainer = document.getElementById('zotero-items-pane-container'); var collectionsPane = document.getElementById("zotero-collections-pane"); var tagSelector = document.getElementById("zotero-tag-selector"); - + let layoutModeMenus = [ + document.getElementById("view-menuitem-standard"), + document.getElementById("view-menuitem-stacked"), + ]; + + let isStackedMode = Zotero.Prefs.get('layout') === 'stacked'; + let isTempStackedMode = Zotero.Prefs.get('tempStackedMode'); + let isItemPaneCollapsed = ZoteroPane.itemPane.collapsed && ZoteroContextPane.collapsed; + + // Keep in sycn with abstracts/variables.scss > $min-width-collections-pane + const collectionsPaneMinWidth = collectionsPane.hasAttribute("collapsed") ? 0 : 200; + // Keep in sycn with abstracts/variables.scss > $min-width-item-pane + const itemPaneMinWidth = (isStackedMode || isItemPaneCollapsed) ? 0 : 320; + const libraryItemPaneMinWidth = (isStackedMode || ZoteroPane.itemPane.collapsed) ? 0 : 320; + // Keep in sycn with abstracts/variables.scss > $width-sidenav + const sideNavMinWidth = isStackedMode ? 0 : 37; + // Keep in sycn with abstracts/variables.scss > $min-width-items-pane + const itemsPaneMinWidth = 370; + + let fixedComponentWidth = collectionsPaneMinWidth + itemPaneMinWidth + sideNavMinWidth; + // Calculate the heights of the components that aren't able to shrink automatically // when the window is resized - let fixedComponentWidth = trees.scrollWidth - itemsPaneContainer.scrollWidth; let fixedComponentHeight = titlebar.scrollHeight + trees.scrollHeight - itemsPaneContainer.scrollHeight; document.documentElement.style.setProperty('--width-of-fixed-components', `${fixedComponentWidth}px`); document.documentElement.style.setProperty('--height-of-fixed-components', `${fixedComponentHeight}px`); + let layoutChanged = false; + // Collections pane + items pane + items pane + sidenav + 3px for draggability + const windowAutoStackMinWidth = 930; + if (window.innerWidth < windowAutoStackMinWidth) { + // Disable layout mode menus because the standard mode is not available + layoutModeMenus.forEach(menu => menu.setAttribute("disabled", "true")); + // If the window is too small in standard mode, enter stack mode temporarily + if (!isStackedMode && !isTempStackedMode) { + Zotero.Prefs.set('tempStackedMode', true); + Zotero.Prefs.set('layout', 'stacked'); + layoutChanged = true; + } + } + else { + layoutModeMenus.forEach(menu => menu.removeAttribute("disabled")); + if (isTempStackedMode) { + Zotero.Prefs.clear('tempStackedMode'); + Zotero.Prefs.set('layout', 'standard'); + layoutChanged = true; + } + } + + if (layoutChanged) { + // Compute the layout constraints again after the layout change to avoid weirdness + setTimeout(() => { + this.updateLayoutConstraints(); + }, 0); + } + + // This is important to avoid other panes be pushed out of the window + collectionsPane.style.setProperty( + "--max-width-collections-pane", + `${window.innerWidth - libraryItemPaneMinWidth - sideNavMinWidth - itemsPaneMinWidth}px`); + var collectionsPaneWidth = collectionsPane.getBoundingClientRect().width; tagSelector.style.maxWidth = collectionsPaneWidth + 'px'; if (ZoteroPane.itemsView) { ZoteroPane.itemsView.updateHeight(); } - // Temp JS solution to shrink the collection search so that it does not overflow outside - // of the collection pane - var collectionSearch = document.getElementById("zotero-collections-search"); - collectionSearch.removeAttribute("data-expanded-width"); - if (collectionsPaneWidth < 220) { - collectionSearch.setAttribute("data-expanded-width", 150); - if (collectionSearch.classList.contains("visible")) { - collectionSearch.style.maxWidth = "150px"; - } - } - else { - collectionSearch.style.removeProperty('max-width'); - } - + this.handleTagSelectorResize(); this.itemPane.handleResize(); diff --git a/chrome/content/zotero/zoteroPane.xhtml b/chrome/content/zotero/zoteroPane.xhtml index 9160421da1..7e20b6354c 100644 --- a/chrome/content/zotero/zoteroPane.xhtml +++ b/chrome/content/zotero/zoteroPane.xhtml @@ -1075,7 +1075,7 @@