use Icons.getCSSIcon instead of getDOMElement (#4338)
- getDOMElement relied on React.renderToStaticMarkup, which is react 18 was moved to a different file than the one exposed with react-dom-server. To not add another file just for that one function, replace getDOMElement with getCSSIcon. - getDOMElement was mainly used for a few remaining png icons that were not replaced with svg. For those few icons, just record which background-url should be set when the module loads and add it in getCSSIcon if applicable. Alternatively, background-image setting could be moved into a stylesheet? - a few hardcoded twisty svgs in icons.jsx are not used anywhere (they would be fetched via IconTwisty), so those are removed
This commit is contained in:
parent
af4bbd2c4d
commit
37991e220e
5 changed files with 17 additions and 97 deletions
|
@ -1,8 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
const { renderToStaticMarkup } = require('react-dom-server');
|
||||
const { PureComponent } = React;
|
||||
const { element, string, object } = require('prop-types');
|
||||
|
||||
const Icon = (props) => {
|
||||
|
@ -51,6 +49,8 @@ CSSItemTypeIcon.propTypes = {
|
|||
|
||||
module.exports = { Icon, CSSIcon, CSSItemTypeIcon };
|
||||
|
||||
// Icons cache for a few remaining png icons till they are replaced
|
||||
let legacyIconsCache = {};
|
||||
|
||||
function i(name, svgOrSrc, hasHiDPI = true) {
|
||||
if (typeof svgOrSrc == 'string' && hasHiDPI && window.devicePixelRatio >= 1.25) {
|
||||
|
@ -59,99 +59,15 @@ function i(name, svgOrSrc, hasHiDPI = true) {
|
|||
parts[parts.length - 2] = parts[parts.length - 2] + '@2x';
|
||||
svgOrSrc = parts.join('.');
|
||||
}
|
||||
|
||||
const icon = class extends PureComponent {
|
||||
render() {
|
||||
let props = Object.assign({}, this.props);
|
||||
props.name = name.toLowerCase();
|
||||
|
||||
if (typeof svgOrSrc == 'string') {
|
||||
if (!("style" in props)) props.style = {};
|
||||
props.style.backgroundImage = `url(${svgOrSrc})`;
|
||||
props.className = props.className || "";
|
||||
props.className += " icon-bg";
|
||||
// We use css background-image.
|
||||
// This is a performance optimization for fast-scrolling trees.
|
||||
// If we use img elements they are slow to render
|
||||
// and produce pop-in when fast-scrolling.
|
||||
return (
|
||||
<Icon {...props} />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Icon {...props}>{svgOrSrc}</Icon>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
icon.propTypes = {
|
||||
className: string
|
||||
}
|
||||
|
||||
icon.displayName = `Icon${name}`
|
||||
|
||||
module.exports[icon.displayName] = icon
|
||||
legacyIconsCache[`Icon${name}`] = svgOrSrc;
|
||||
}
|
||||
|
||||
/* eslint-disable max-len */
|
||||
|
||||
|
||||
i('Twisty', (
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 13.4c-.5 0-.9-.2-1.2-.6L.4 5.2C0 4.7-.1 4.3.2 3.7S1 3 1.6 3h12.8c.6 0 1.2.1 1.4.7.3.6.2 1.1-.2 1.6l-6.4 7.6c-.3.4-.7.5-1.2.5z"/>
|
||||
</svg>
|
||||
));
|
||||
i('Cross', "chrome://zotero/skin/cross.png");
|
||||
i('Tick', "chrome://zotero/skin/tick.png");
|
||||
i('ArrowRefresh', "chrome://zotero/skin/arrow_refresh.png");
|
||||
|
||||
if (Zotero.isMac) {
|
||||
i('Twisty', (
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<polyline points="3 4 12 4 7.5 12"/>
|
||||
</svg>
|
||||
));
|
||||
}
|
||||
|
||||
if (Zotero.isWin) {
|
||||
i('Twisty', (
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 1792 1792">
|
||||
<path d="M1395 736q0 13-10 23l-466 466q-10 10-23 10t-23-10l-466-466q-10-10-10-23t10-23l50-50q10-10 23-10t23 10l393 393 393-393q10-10 23-10t23 10l50 50q10 10 10 23z"/>
|
||||
</svg>
|
||||
));
|
||||
}
|
||||
|
||||
let domElementCache = {};
|
||||
|
||||
/**
|
||||
* Returns a DOM element for the icon class
|
||||
*
|
||||
* To be used in itemTree where rendering is done without react
|
||||
* for performance reasons
|
||||
* @param {String} icon
|
||||
* @returns {Element}
|
||||
*/
|
||||
module.exports.getDOMElement = function (icon) {
|
||||
if (domElementCache[icon]) return domElementCache[icon].cloneNode(true);
|
||||
if (!module.exports[icon]) {
|
||||
Zotero.debug(`Attempting to get non-existant icon ${icon}`);
|
||||
return "";
|
||||
}
|
||||
let div = document.createElement('div');
|
||||
div.innerHTML = renderToStaticMarkup(React.createElement(module.exports[icon]));
|
||||
domElementCache[icon] = div.firstChild;
|
||||
return domElementCache[icon].cloneNode(true);
|
||||
};
|
||||
|
||||
let cssIconsCache = new Map();
|
||||
|
||||
|
@ -161,6 +77,11 @@ module.exports.getCSSIcon = function (key) {
|
|||
iconEl.classList.add('icon');
|
||||
iconEl.classList.add('icon-css');
|
||||
iconEl.classList.add(`icon-${key}`);
|
||||
// Temporarily set background image for a few remaining png icons
|
||||
if (legacyIconsCache[key]) {
|
||||
iconEl.style.backgroundImage = `url(${legacyIconsCache[key]})`;
|
||||
iconEl.classList.add("icon-bg");
|
||||
}
|
||||
cssIconsCache.set(key, iconEl);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
*/
|
||||
import React, { memo, useCallback, useEffect, useRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { getDOMElement } from 'components/icons';
|
||||
import { getCSSIcon } from 'components/icons';
|
||||
|
||||
import VirtualizedTable, { renderCell } from 'components/virtualized-table';
|
||||
import { nextHTMLID, noop } from './utils';
|
||||
|
@ -32,13 +32,13 @@ import { nextHTMLID, noop } from './utils';
|
|||
|
||||
function getImageByStatus(status) {
|
||||
if (status === Zotero.ProgressQueue.ROW_PROCESSING) {
|
||||
return getDOMElement('IconArrowRefresh');
|
||||
return getCSSIcon('IconArrowRefresh');
|
||||
}
|
||||
else if (status === Zotero.ProgressQueue.ROW_FAILED) {
|
||||
return getDOMElement('IconCross');
|
||||
return getCSSIcon('IconCross');
|
||||
}
|
||||
else if (status === Zotero.ProgressQueue.ROW_SUCCEEDED) {
|
||||
return getDOMElement('IconTick');
|
||||
return getCSSIcon('IconTick');
|
||||
}
|
||||
return document.createElement('span');
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ const PropTypes = require('prop-types');
|
|||
const cx = require('classnames');
|
||||
const WindowedList = require('./windowed-list');
|
||||
const Draggable = require('./draggable');
|
||||
const { CSSIcon, getDOMElement } = require('components/icons');
|
||||
const { CSSIcon, getCSSIcon } = require('components/icons');
|
||||
const { Zotero_Tooltip } = require('./tooltip');
|
||||
|
||||
const TYPING_TIMEOUT = 1000;
|
||||
|
@ -1751,7 +1751,7 @@ function renderCheckboxCell(index, data, column, dir = null) {
|
|||
span.setAttribute('role', 'checkbox');
|
||||
span.setAttribute('aria-checked', data);
|
||||
if (data) {
|
||||
span.appendChild(getDOMElement('IconTick'));
|
||||
span.appendChild(getCSSIcon('IconTick'));
|
||||
}
|
||||
return span;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ const LibraryTree = require('./libraryTree');
|
|||
const VirtualizedTable = require('components/virtualized-table');
|
||||
const { renderCell, formatColumnName } = VirtualizedTable;
|
||||
const Icons = require('components/icons');
|
||||
const { getDOMElement, getCSSIcon, getCSSItemTypeIcon } = Icons;
|
||||
const { getCSSIcon, getCSSItemTypeIcon } = Icons;
|
||||
const { COLUMNS } = require("zotero/itemTreeColumns");
|
||||
const { Cc, Ci, Cu, ChromeUtils } = require('chrome');
|
||||
const { OS } = ChromeUtils.importESModule("chrome://zotero/content/osfile.mjs");
|
||||
|
@ -2796,7 +2796,7 @@ var ItemTree = class ItemTree extends LibraryTree {
|
|||
let retracted = "";
|
||||
let retractedAriaLabel = "";
|
||||
if (Zotero.Retractions.isRetracted(item)) {
|
||||
retracted = getDOMElement('IconCross');
|
||||
retracted = getCSSIcon("IconCross");
|
||||
retracted.classList.add("retracted");
|
||||
retractedAriaLabel = Zotero.getString('retraction.banner');
|
||||
}
|
||||
|
@ -2916,7 +2916,7 @@ var ItemTree = class ItemTree extends LibraryTree {
|
|||
}
|
||||
//else if (type == 'none') {
|
||||
// if (item.getField('url') || item.getField('DOI')) {
|
||||
// icon = getDOMElement('IconLink');
|
||||
// icon = getCSSIcon('IconLink');
|
||||
// ariaLabel = Zotero.getString('pane.item.attachments.hasLink');
|
||||
// icon.classList.add('cell-icon');
|
||||
// }
|
||||
|
|
|
@ -30,7 +30,6 @@ Components.utils.import("resource://zotero/config.js");
|
|||
var React = require('react');
|
||||
var ReactDOM = require('react-dom');
|
||||
var VirtualizedTable = require('components/virtualized-table');
|
||||
var { getDOMElement } = require('components/icons');
|
||||
var { renderCell } = VirtualizedTable;
|
||||
|
||||
Zotero_Preferences.Sync = {
|
||||
|
|
Loading…
Reference in a new issue