From 555c78f536d9a6d1f8a11d6dd20f071a32713900 Mon Sep 17 00:00:00 2001
From: Deluan <deluan@deluan.com>
Date: Thu, 30 Apr 2020 21:26:30 -0400
Subject: [PATCH] Reduce flickering of album covers

---
 ui/package-lock.json          | 16 ++++++++++++
 ui/package.json               |  1 +
 ui/src/album/AlbumGridView.js | 46 +++++++++++++++++++++++------------
 3 files changed, 47 insertions(+), 16 deletions(-)

diff --git a/ui/package-lock.json b/ui/package-lock.json
index 4f15853f2..3f1df9cf5 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -6796,6 +6796,11 @@
       "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
       "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
     },
+    "get-node-dimensions": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/get-node-dimensions/-/get-node-dimensions-1.2.1.tgz",
+      "integrity": "sha512-2MSPMu7S1iOTL+BOa6K1S62hB2zUAYNF/lV0gSVlOaacd087lc6nR1H1r0e3B1CerTo+RceOmi1iJW+vp21xcQ=="
+    },
     "get-own-enumerable-property-symbols": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz",
@@ -13737,6 +13742,17 @@
       "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
       "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
     },
+    "react-measure": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/react-measure/-/react-measure-2.3.0.tgz",
+      "integrity": "sha512-dwAvmiOeblj5Dvpnk8Jm7Q8B4THF/f1l1HtKVi0XDecsG6LXwGvzV5R1H32kq3TW6RW64OAf5aoQxpIgLa4z8A==",
+      "requires": {
+        "@babel/runtime": "^7.2.0",
+        "get-node-dimensions": "^1.2.1",
+        "prop-types": "^15.6.2",
+        "resize-observer-polyfill": "^1.5.0"
+      }
+    },
     "react-redux": {
       "version": "7.2.0",
       "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.0.tgz",
diff --git a/ui/package.json b/ui/package.json
index 90c2ecadf..8a6b682b0 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -18,6 +18,7 @@
     "react-admin": "^3.4.2",
     "react-dom": "^16.13.1",
     "react-jinke-music-player": "^4.12.0",
+    "react-measure": "^2.3.0",
     "react-redux": "^7.2.0",
     "react-scripts": "^3.4.1"
   },
diff --git a/ui/src/album/AlbumGridView.js b/ui/src/album/AlbumGridView.js
index 3761fc923..295dd36cd 100644
--- a/ui/src/album/AlbumGridView.js
+++ b/ui/src/album/AlbumGridView.js
@@ -4,6 +4,7 @@ import { makeStyles } from '@material-ui/core/styles'
 import withWidth from '@material-ui/core/withWidth'
 import { Link } from 'react-router-dom'
 import { linkToRecord, Loading } from 'react-admin'
+import { withContentRect } from 'react-measure'
 import subsonic from '../subsonic'
 import { ArtistLinkField } from './ArtistLinkField'
 import AlbumContextMenu from './AlbumContextMenu.js'
@@ -16,11 +17,6 @@ const useStyles = makeStyles((theme) => ({
     minHeight: '180px',
     minWidth: '180px',
   },
-  cover: {
-    display: 'inline-block',
-    width: '100%',
-    height: '100%',
-  },
   tileBar: {
     textAlign: 'left',
     background:
@@ -38,14 +34,40 @@ const useStyles = makeStyles((theme) => ({
   },
 }))
 
+const useCoverStyles = makeStyles({
+  cover: {
+    display: 'inline-block',
+    width: '100%',
+    height: (props) => props.height,
+  },
+})
+
 const getColsForWidth = (width) => {
   if (width === 'xs') return 2
   if (width === 'sm') return 4
   if (width === 'md') return 5
-  if (width === 'lg') return 6
-  return 7
+  return 6
 }
 
+const Cover = withContentRect('bounds')(
+  ({ album, measureRef, contentRect }) => {
+    // Force height to be the same as the width determined by the GridList
+    // noinspection JSSuspiciousNameCombination
+    const classes = useCoverStyles({ height: contentRect.bounds.width })
+    return (
+      <div ref={measureRef}>
+        <img
+          src={subsonic.url('getCoverArt', album.coverArtId || 'not_found', {
+            size: 300,
+          })}
+          alt={album.album}
+          className={classes.cover}
+        />
+      </div>
+    )
+  }
+)
+
 const LoadedAlbumGrid = ({ ids, data, basePath, width }) => {
   const classes = useStyles()
 
@@ -59,15 +81,7 @@ const LoadedAlbumGrid = ({ ids, data, basePath, width }) => {
             key={id}
             to={linkToRecord(basePath, data[id].id, 'show')}
           >
-            <img
-              src={subsonic.url(
-                'getCoverArt',
-                data[id].coverArtId || 'not_found',
-                { size: 300 }
-              )}
-              alt={data[id].album}
-              className={classes.cover}
-            />
+            <Cover album={data[id]} />
             <GridListTileBar
               className={classes.tileBar}
               title={data[id].name}