Generic Grid with viewport hook working well; need better way to fetch first item's height (error)

This commit is contained in:
James Barnsley
2021-02-27 21:45:00 +13:00
parent e2b580d2c5
commit a67a4a7f67
31 changed files with 1204 additions and 1714 deletions

View File

@ -1,4 +1,3 @@
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
@ -6,10 +5,9 @@ import { Route, Switch } from 'react-router-dom';
import ErrorMessage from '../components/ErrorMessage';
import Link from '../components/Link';
import TrackList from '../components/TrackList';
import AlbumGrid from '../components/AlbumGrid';
import Thumbnail from '../components/Thumbnail';
import Parallax from '../components/Parallax';
import ArtistGrid from '../components/ArtistGrid';
import { Grid } from '../components/Grid';
import RelatedArtists from '../components/RelatedArtists';
import FollowButton from '../components/Fields/FollowButton';
import ContextMenuTrigger from '../components/ContextMenuTrigger';
@ -305,7 +303,7 @@ class Artist extends React.Component {
</h4>
<section className="grid-wrapper no-top-padding">
<AlbumGrid albums={albums} />
<Grid items={albums} />
</section>
</div>
</div>
@ -381,7 +379,7 @@ class Artist extends React.Component {
return (
<div className="body related-artists">
<section className="grid-wrapper no-top-padding">
<ArtistGrid artists={artist.related_artists} />
<Grid items={artist.related_artists} />
</section>
</div>
);

View File

@ -1,10 +1,9 @@
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import ErrorMessage from '../components/ErrorMessage';
import Thumbnail from '../components/Thumbnail';
import PlaylistGrid from '../components/PlaylistGrid';
import { Grid } from '../components/Grid';
import FollowButton from '../components/Fields/FollowButton';
import Parallax from '../components/Parallax';
import { nice_number } from '../components/NiceNumber';
@ -190,7 +189,7 @@ class User extends React.Component {
<h4>
<I18n path="playlist.title_plural" />
</h4>
<PlaylistGrid playlists={playlists} />
<Grid items={playlists} />
</section>
</div>
</div>

View File

@ -1,16 +1,15 @@
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import Header from '../../components/Header';
import Icon from '../../components/Icon';
import CategoryGrid from '../../components/CategoryGrid';
import { Grid } from '../../components/Grid';
import Loader from '../../components/Loader';
import * as uiActions from '../../services/ui/actions';
import * as spotifyActions from '../../services/spotify/actions';
import {
isLoading,
} from '../../util/helpers';
encodeUri,
} from '../../util/format';
import { i18n, I18n } from '../../locale';
import { indexToArray } from '../../util/arrays';
import { makeLoadingSelector } from '../../util/selectors';
@ -54,7 +53,11 @@ class DiscoverCategories extends React.Component {
<I18n path="discover.categories.title" />
</Header>
<section className="content-wrapper grid-wrapper">
<CategoryGrid categories={categories} />
<Grid
className="grid--tiles"
items={categories}
getLink={(item) => `/discover/categories/${encodeUri(item.uri)}`}
/>
</section>
</div>
);

View File

@ -3,7 +3,7 @@ import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import Header from '../../components/Header';
import Icon from '../../components/Icon';
import PlaylistGrid from '../../components/PlaylistGrid';
import { Grid } from '../../components/Grid';
import Loader from '../../components/Loader';
import ErrorMessage from '../../components/ErrorMessage';
import Button from '../../components/Button';
@ -117,7 +117,7 @@ class DiscoverCategory extends React.Component {
</Header>
<div className="content-wrapper">
<section className="grid-wrapper">
<PlaylistGrid playlists={playlists} />
<Grid items={playlists} />
</section>
</div>
</div>

View File

@ -1,8 +1,7 @@
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import PlaylistGrid from '../../components/PlaylistGrid';
import { Grid } from '../../components/Grid';
import Header from '../../components/Header';
import Icon from '../../components/Icon';
import Loader from '../../components/Loader';
@ -100,7 +99,7 @@ class DiscoverFeatured extends React.Component {
<I18n path="discover.featured.title" />
</Header>
<section className="content-wrapper grid-wrapper">
{<PlaylistGrid playlists={playlists} />}
<Grid items={playlists} />
</section>
</div>
);

View File

@ -1,10 +1,9 @@
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import Header from '../../components/Header';
import Icon from '../../components/Icon';
import AlbumGrid from '../../components/AlbumGrid';
import { Grid } from '../../components/Grid';
import Parallax from '../../components/Parallax';
import LazyLoadListener from '../../components/LazyLoadListener';
import Loader from '../../components/Loader';
@ -130,7 +129,7 @@ class DiscoverNewReleases extends React.Component {
<I18n path="discover.new_releases.title" />
</Header>
<section className="content-wrapper grid-wrapper">
<AlbumGrid albums={albums} />
<Grid items={albums} />
</section>
<LazyLoadListener
loadKey={more}

View File

@ -3,7 +3,7 @@ import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { compact } from 'lodash';
import InputRange from 'react-input-range';
import AlbumGrid from '../../components/AlbumGrid';
import { Grid } from '../../components/Grid';
import TrackList from '../../components/TrackList';
import Thumbnail from '../../components/Thumbnail';
import Parallax from '../../components/Parallax';
@ -497,7 +497,7 @@ class Discover extends React.Component {
<br />
<section>
<h4><I18n path="discover.recommendations.albums" /></h4>
<AlbumGrid className="grid--mini" albums={albums} />
<Grid items={albums} mini />
</section>
</div>

View File

@ -1,13 +1,11 @@
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import AlbumGrid from '../../components/AlbumGrid';
import List from '../../components/List';
import Header from '../../components/Header';
import DropdownField from '../../components/Fields/DropdownField';
import FilterField from '../../components/Fields/FilterField';
import LazyLoadListener from '../../components/LazyLoadListener';
import { Grid } from '../../components/Grid';
import Icon from '../../components/Icon';
import * as coreActions from '../../services/core/actions';
import * as uiActions from '../../services/ui/actions';
@ -35,28 +33,16 @@ class LibraryAlbums extends React.Component {
this.state = {
filter: '',
limit: 50,
per_page: 50,
};
}
componentDidMount() {
const {
location: {
state = {},
},
uiActions: {
setWindowTitle,
},
} = this.props;
// Restore any limit defined in our location state
if (state.limit) {
this.setState({
limit: state.limit,
});
}
setWindowTitle(i18n('library.albums.title'));
this.getMopidyLibrary();
this.getGoogleLibrary();
@ -147,23 +133,6 @@ class LibraryAlbums extends React.Component {
});
}
loadMore = () => {
const {
limit,
per_page,
} = this.state;
const {
location: {
state,
},
history,
} = this.props;
const new_limit = limit + per_page;
this.setState({ limit: new_limit });
history.replace({ state: { ...state, limit: new_limit } });
}
setSort = (value) => {
const {
sort,
@ -190,7 +159,6 @@ class LibraryAlbums extends React.Component {
loading_progress,
} = this.props;
const {
limit,
filter,
} = this.state;
let { albums } = this.props;
@ -207,10 +175,6 @@ class LibraryAlbums extends React.Component {
albums = applyFilter('name', filter, albums);
}
// Apply our lazy-load-rendering
const total_albums = albums.length;
albums = albums.slice(0, limit);
if (view === 'list') {
return (
<section className="content-wrapper">
@ -223,25 +187,12 @@ class LibraryAlbums extends React.Component {
className="albums"
link_prefix="/album/"
/>
<LazyLoadListener
loadKey={total_albums > limit ? limit : total_albums}
showLoader={limit < total_albums}
loadMore={this.loadMore}
/>
</section>
);
}
return (
<section className="content-wrapper">
<AlbumGrid
handleContextMenu={this.handleContextMenu}
albums={albums}
/>
<LazyLoadListener
loadKey={total_albums > limit ? limit : total_albums}
showLoader={limit < total_albums}
loadMore={this.loadMore}
/>
<Grid items={albums} />
</section>
);
}

View File

@ -1,13 +1,11 @@
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import Header from '../../components/Header';
import ArtistGrid from '../../components/ArtistGrid';
import List from '../../components/List';
import DropdownField from '../../components/Fields/DropdownField';
import FilterField from '../../components/Fields/FilterField';
import LazyLoadListener from '../../components/LazyLoadListener';
import { Grid } from '../../components/Grid';
import Icon from '../../components/Icon';
import * as uiActions from '../../services/ui/actions';
import * as coreActions from '../../services/core/actions';
@ -32,8 +30,6 @@ class LibraryArtists extends React.Component {
this.state = {
filter: '',
limit: 50,
per_page: 50,
};
}
@ -44,14 +40,6 @@ class LibraryArtists extends React.Component {
},
} = this.props;
// Restore any limit defined in our location state
const state = (this.props.location.state ? this.props.location.state : {});
if (state.limit) {
this.setState({
limit: state.limit,
});
}
setWindowTitle(i18n('library.artists.title'));
this.getMopidyLibrary();
@ -147,17 +135,6 @@ class LibraryArtists extends React.Component {
loadLibrary('spotify:library:artists', { forceRefetch });
};
loadMore = () => {
const new_limit = this.state.limit + this.state.per_page;
this.setState({ limit: new_limit });
// Set our pagination to location state
const state = (this.props.location && this.props.location.state ? this.props.location.state : {});
state.limit = new_limit;
this.props.history.replace({ state });
}
renderView = () => {
const {
sort,
@ -166,7 +143,6 @@ class LibraryArtists extends React.Component {
loading_progress,
} = this.props;
const {
limit,
filter,
} = this.state;
let { artists } = this.props;
@ -185,10 +161,6 @@ class LibraryArtists extends React.Component {
artists = applyFilter('name', filter, artists);
}
// Apply our lazy-load-rendering
const total_artists = artists.length;
artists = artists.slice(0, limit);
if (view === 'list') {
return (
<section className="content-wrapper">
@ -201,25 +173,12 @@ class LibraryArtists extends React.Component {
className="artists"
link_prefix="/artist/"
/>
<LazyLoadListener
loadKey={total_artists > limit ? limit : total_artists}
showLoader={limit < total_artists}
loadMore={() => this.loadMore()}
/>
</section>
);
}
return (
<section className="content-wrapper">
<ArtistGrid
handleContextMenu={(e, item) => this.handleContextMenu(e, item)}
artists={artists}
/>
<LazyLoadListener
loadKey={total_artists > limit ? limit : total_artists}
showLoader={limit < total_artists}
loadMore={() => this.loadMore()}
/>
<Grid items={artists} />
</section>
);
}

View File

@ -2,10 +2,9 @@ import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import Header from '../../components/Header';
import GridItem from '../../components/GridItem';
import { Grid } from '../../components/Grid';
import Loader from '../../components/Loader';
import Icon from '../../components/Icon';
import ErrorBoundary from '../../components/ErrorBoundary';
import * as uiActions from '../../services/ui/actions';
import * as mopidyActions from '../../services/mopidy/actions';
import { formatImages, encodeUri } from '../../util/format';
@ -119,21 +118,7 @@ class LibraryBrowse extends React.Component {
</Header>
<section className="content-wrapper">
<div className="grid grid--tiles">
<ErrorBoundary>
{
grid_items.map(
(item, index) => (
<GridItem
item={item}
key={index}
link={item.link}
mopidyActions={mopidyActions}
type="browse"
/>
),
)
}
</ErrorBoundary>
<Grid items={grid_items} />
</div>
</section>
</div>

View File

@ -5,7 +5,7 @@ import Loader from '../../components/Loader';
import Header from '../../components/Header';
import List from '../../components/List';
import TrackList from '../../components/TrackList';
import GridItem from '../../components/GridItem';
import { Grid } from '../../components/Grid';
import DropdownField from '../../components/Fields/DropdownField';
import FilterField from '../../components/Fields/FilterField';
import Icon from '../../components/Icon';
@ -51,21 +51,7 @@ const Subdirectories = ({ items, view }) => {
);
}
return (
<div className="grid category-grid">
{
items.map((item) => (
<GridItem
key={item.uri}
type="directory"
link={link(item)}
item={item}
nocontext
/>
))
}
</div>
);
return <Grid items={items} nocontext link={(item) => link(item)} />
};
class LibraryBrowseDirectory extends React.Component {

View File

@ -3,7 +3,7 @@ import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import Button from '../../components/Button';
import PlaylistGrid from '../../components/PlaylistGrid';
import { Grid } from '../../components/Grid';
import List from '../../components/List';
import DropdownField from '../../components/Fields/DropdownField';
import Header from '../../components/Header';
@ -33,27 +33,15 @@ class LibraryPlaylists extends React.Component {
this.state = {
filter: '',
limit: 50,
per_page: 50,
};
}
componentDidMount() {
const {
location: {
state: {
limit,
} = {},
} = {},
uiActions: {
setWindowTitle,
},
} = this.props;
if (limit) {
this.setState({
limit,
});
}
setWindowTitle(i18n('library.playlists.title'));
@ -134,17 +122,6 @@ class LibraryPlaylists extends React.Component {
this.props.uiActions.showContextMenu(data);
}
loadMore() {
const new_limit = this.state.limit + this.state.per_page;
this.setState({ limit: new_limit });
// Set our pagination to location state
const state = (this.props.location && this.props.location.state ? this.props.location.state : {});
state.limit = new_limit;
this.props.history.replace({ state });
}
renderView = () => {
const {
sort,
@ -155,7 +132,6 @@ class LibraryPlaylists extends React.Component {
} = this.props;
const {
filter,
limit,
} = this.state;
if (loading_progress) {
@ -172,10 +148,6 @@ class LibraryPlaylists extends React.Component {
playlists = applyFilter('name', filter, playlists);
}
// Apply our lazy-load-rendering
const total_playlists = playlists.length;
playlists = playlists.slice(0, limit);
if (view === 'list') {
return (
<section className="content-wrapper">
@ -188,25 +160,12 @@ class LibraryPlaylists extends React.Component {
className="playlists"
link_prefix="/playlist/"
/>
<LazyLoadListener
loadKey={total_playlists > limit ? limit : total_playlists}
loading={limit < total_playlists}
loadMore={() => this.loadMore()}
/>
</section>
);
}
return (
<section className="content-wrapper">
<PlaylistGrid
handleContextMenu={(e, item) => this.handleContextMenu(e, item)}
playlists={playlists}
/>
<LazyLoadListener
loadKey={total_playlists > limit ? limit : total_playlists}
loading={limit < total_playlists}
loadMore={() => this.loadMore()}
/>
<Grid items={playlists} />
</section>
);
}