diff --git a/css/playlist-window.css b/css/playlist-window.css
index 74825f50..213879d0 100644
--- a/css/playlist-window.css
+++ b/css/playlist-window.css
@@ -50,52 +50,32 @@
#winamp2-js .playlist-middle-center {
flex-grow: 1;
padding: 3px 0;
+ min-width: 0; /* Not sure why this is needed */
}
#winamp2-js .playlist-tracks {
- overflow: hidden;
- height: 100%;
-}
-#winamp2-js .playlist-tracks > div {
- width: 100%;
- display: table;
-}
-
-#winamp2-js .playlist-track {
+ display: flex;
+ flex: 1 0 auto;
font-size: 9px;
- display: table-row;
line-height: 13px;
letter-spacing: 0.5px;
user-select: none;
}
-#winamp2-js .playlist-track-number {
- text-align: right;
+#winamp2-js .playlist-track-numbers > div,
+#winamp2-js .playlist-track-durations > div {
padding-right: 3px;
- display: table-cell;
- width: 1%;
- white-space: nowrap;
}
-#winamp2-js .playlist-track-title {
- flex-grow: 1;
- display: table-cell;
- width: auto;
+#winamp2-js .playlist-track-titles {
+ flex: 1 1 auto;
+ overflow: hidden;
}
-#winamp2-js .playlist-track-title > span {
+#winamp2-js .playlist-track-titles > div {
+ text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
- display: block;
- text-overflow: ellipsis;
- position: relative;
-}
-
-#winamp2-js .playlist-track-duration {
- padding-right: 3px;
- display: table-cell;
- width: 1%;
- white-space: nowrap;
}
#winamp2-js .playlist-middle-right {
diff --git a/js/components/PlaylistWindow/Track.js b/js/components/PlaylistWindow/TrackCell.js
similarity index 74%
rename from js/components/PlaylistWindow/Track.js
rename to js/components/PlaylistWindow/TrackCell.js
index 22085780..abe027fd 100644
--- a/js/components/PlaylistWindow/Track.js
+++ b/js/components/PlaylistWindow/TrackCell.js
@@ -1,24 +1,21 @@
import React from "react";
import { connect } from "react-redux";
import classnames from "classnames";
-import { getTimeStr } from "../../utils";
import {
CLICKED_TRACK,
CTRL_CLICKED_TRACK,
PLAY_TRACK
} from "../../actionTypes";
-const Track = props => {
+const TrackCell = props => {
const {
skinPlaylistStyle,
selected,
current,
- title,
- number,
- duration,
clickTrack,
ctrlClickTrack,
- playTrack
+ playTrack,
+ children
} = props;
const style = {
backgroundColor: selected ? skinPlaylistStyle.selectedbg : null,
@@ -26,17 +23,13 @@ const Track = props => {
};
return (
-
{number}.
-
- {title}
-
-
{getTimeStr(duration)}
+ {children}
);
};
@@ -51,8 +44,6 @@ const mapStateToProps = (state, ownProps) => {
return {
skinPlaylistStyle,
selected: track.selected,
- title: track.title,
- duration: track.duration,
current: currentTrack === ownProps.id
};
};
@@ -70,4 +61,4 @@ const mapDispatchToProps = (dispatch, ownProps) => ({
playTrack: () => dispatch({ type: PLAY_TRACK, id: ownProps.id })
});
-export default connect(mapStateToProps, mapDispatchToProps)(Track);
+export default connect(mapStateToProps, mapDispatchToProps)(TrackCell);
diff --git a/js/components/PlaylistWindow/TrackList.js b/js/components/PlaylistWindow/TrackList.js
new file mode 100644
index 00000000..b256909a
--- /dev/null
+++ b/js/components/PlaylistWindow/TrackList.js
@@ -0,0 +1,44 @@
+import React from "react";
+import { connect } from "react-redux";
+
+import { getTimeStr } from "../../utils";
+import { getVisibleTrackIds } from "../../selectors";
+import TrackCell from "./TrackCell";
+
+const TrackList = props => {
+ const { trackIds, tracks } = props;
+ return (
+
+
+ {trackIds.map((id, i) => (
+
+ {`${i + 1}.`}
+
+ ))}
+
+
+ {trackIds.map(id => (
+
+ {tracks[id].title}
+
+ ))}
+
+
+ {trackIds.map(id => (
+
+ {getTimeStr(tracks[id].duration)}
+
+ ))}
+
+
+ );
+};
+
+const mapDispatchToProps = () => ({});
+
+const mapStateToProps = state => ({
+ trackIds: getVisibleTrackIds(state),
+ tracks: state.tracks
+});
+
+export default connect(mapStateToProps, mapDispatchToProps)(TrackList);
diff --git a/js/components/PlaylistWindow/__snapshots__/index.test.js.snap b/js/components/PlaylistWindow/__snapshots__/index.test.js.snap
index 2ef00cc5..136c940a 100644
--- a/js/components/PlaylistWindow/__snapshots__/index.test.js.snap
+++ b/js/components/PlaylistWindow/__snapshots__/index.test.js.snap
@@ -52,7 +52,15 @@ exports[`PlaylistWindow renders to snapshot 1`] = `
;
@@ -50,12 +48,13 @@ const PlaylistWindow = props => {
focused,
playlistScrollPosition,
setPlaylistScrollPosition,
- trackOrder,
playlistSize,
playlistShade,
close,
- toggleShade
+ toggleShade,
+ allTracksAreVisible
} = props;
+ console.log({ allTracksAreVisible });
if (playlistShade) {
return
;
}
@@ -75,22 +74,6 @@ const PlaylistWindow = props => {
wide: playlistSize[0] > 2
});
- const BASE_WINDOW_HEIGHT = 52;
- const numberOfVisibleTracks = Math.floor(
- (BASE_WINDOW_HEIGHT + PLAYLIST_RESIZE_SEGMENT_HEIGHT * playlistSize[1]) /
- TRACK_HEIGHT
- );
- const overflowTracks = Math.max(0, trackOrder.length - numberOfVisibleTracks);
- const offset = percentToIndex(
- playlistScrollPosition / 100,
- overflowTracks + 1
- );
-
- // Ugh. By not rendering some tracks, we can end up in a situation where
- // scrolling causes the number of digits in the tracks to go up, thus causing
- // a horizontal jump.
- const tracks = trackOrder.slice(offset, offset + numberOfVisibleTracks);
-
return (
{
-
-
- {tracks.map((id, i) => (
-
- ))}
-
-
+
{
onChange={setPlaylistScrollPosition}
vertical
handle={Handle}
- disabled={overflowTracks === 0}
+ disabled={allTracksAreVisible}
/>
@@ -177,6 +154,7 @@ const mapDispatchToProps = (dispatch, ownProps) => ({
stop: () => dispatch(stop()),
openFileDialog: () => dispatch(openFileDialog(ownProps.fileInput)),
setPlaylistScrollPosition: position =>
+ // TODO: Move this to an action creator so we can see if this is actually changing
dispatch({ type: SET_PLAYLIST_SCROLL_POSITION, position: 100 - position }),
close: () => dispatch({ type: TOGGLE_PLAYLIST_WINDOW }),
toggleShade: () => dispatch({ type: TOGGLE_PLAYLIST_SHADE_MODE }),
@@ -192,16 +170,18 @@ const mapStateToProps = state => {
playlistSize,
playlistShade
},
- media: { duration }
+ media: { duration },
+ playlist: { trackOrder }
} = state;
+
return {
focused,
skinPlaylistStyle,
playlistScrollPosition,
playlistSize,
playlistShade,
- trackOrder: getOrderedTracks(state),
- duration
+ duration,
+ allTracksAreVisible: getVisibleTrackIds(state).length === trackOrder.length
};
};
diff --git a/js/selectors.js b/js/selectors.js
index 032506a1..d0ba9447 100644
--- a/js/selectors.js
+++ b/js/selectors.js
@@ -1,5 +1,5 @@
-import { denormalize, getTimeStr, clamp } from "./utils";
-import { BANDS } from "./constants";
+import { denormalize, getTimeStr, clamp, percentToIndex } from "./utils";
+import { BANDS, PLAYLIST_RESIZE_SEGMENT_HEIGHT } from "./constants";
import { createSelector } from "reselect";
export const getEqfData = state => {
@@ -87,3 +87,34 @@ export const nextTrack = (state, n = 1) => {
nextIndex = clamp(nextIndex, 0, trackOrder.length - 1);
return trackOrder[nextIndex];
};
+
+export const getPlaylistScrollPosition = state =>
+ state.display.playlistScrollPosition;
+
+const TRACK_HEIGHT = 13;
+const BASE_WINDOW_HEIGHT = 52;
+export const getNumberOfVisibleTracks = state => {
+ const { playlistSize } = state.display;
+ return Math.floor(
+ (BASE_WINDOW_HEIGHT + PLAYLIST_RESIZE_SEGMENT_HEIGHT * playlistSize[1]) /
+ TRACK_HEIGHT
+ );
+};
+
+export const getOverflowTrackCount = createSelector(
+ getTrackOrder,
+ getNumberOfVisibleTracks,
+ (trackOrder, numberOfVisibleTracks) =>
+ Math.max(0, trackOrder.length - numberOfVisibleTracks)
+);
+
+export const getVisibleTrackIds = createSelector(
+ getPlaylistScrollPosition,
+ getTrackOrder,
+ getNumberOfVisibleTracks,
+ (playlistScrollPosition, trackOrder, numberOfVisibleTracks) => {
+ const overflow = Math.max(0, trackOrder.length - numberOfVisibleTracks);
+ const offset = percentToIndex(playlistScrollPosition / 100, overflow + 1);
+ return trackOrder.slice(offset, offset + numberOfVisibleTracks);
+ }
+);