From 9b3cedafc23f9387e93adde7d3018bcabce52af6 Mon Sep 17 00:00:00 2001 From: Jordan Eldredge Date: Thu, 5 Dec 2019 23:29:00 -0800 Subject: [PATCH] Remove LibraryTable --- .../MediaLibraryWindow/AlbumsTable.tsx | 17 ---- .../MediaLibraryWindow/ArtistsTable.tsx | 19 ---- .../MediaLibraryWindow/LibraryTable.tsx | 72 -------------- .../MediaLibraryWindow/TracksTable.tsx | 93 ------------------- js/components/MediaLibraryWindow/index.tsx | 9 +- js/selectors.ts | 12 --- js/trackUtils.ts | 9 -- js/utils.test.ts | 87 ----------------- js/utils.ts | 36 ------- 9 files changed, 3 insertions(+), 351 deletions(-) delete mode 100644 js/components/MediaLibraryWindow/AlbumsTable.tsx delete mode 100644 js/components/MediaLibraryWindow/ArtistsTable.tsx delete mode 100644 js/components/MediaLibraryWindow/LibraryTable.tsx delete mode 100644 js/components/MediaLibraryWindow/TracksTable.tsx diff --git a/js/components/MediaLibraryWindow/AlbumsTable.tsx b/js/components/MediaLibraryWindow/AlbumsTable.tsx deleted file mode 100644 index 6db9dd98..00000000 --- a/js/components/MediaLibraryWindow/AlbumsTable.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as React from "react"; -import LibraryTable from "./LibraryTable"; - -const AlbumsTable = React.memo(() => { - return ( - - ); -}); - -export default AlbumsTable; diff --git a/js/components/MediaLibraryWindow/ArtistsTable.tsx b/js/components/MediaLibraryWindow/ArtistsTable.tsx deleted file mode 100644 index 7e6e58b2..00000000 --- a/js/components/MediaLibraryWindow/ArtistsTable.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import * as React from "react"; -import LibraryTable from "./LibraryTable"; - -interface Props {} - -export default class ArtistsTable extends React.Component { - render() { - return ( - - ); - } -} diff --git a/js/components/MediaLibraryWindow/LibraryTable.tsx b/js/components/MediaLibraryWindow/LibraryTable.tsx deleted file mode 100644 index 3c81cd7b..00000000 --- a/js/components/MediaLibraryWindow/LibraryTable.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import React, { useState } from "react"; -import classnames from "classnames"; - -interface Props { - headings: Array; - rows: Array>; - widths: Array; -} - -export default function LibraryTable(props: Props) { - const [selectedRow, setSelectedRow] = useState(null); - const rowStyle = { - display: "grid", - gridTemplateColumns: props.widths.map(width => `${width}px`).join(" "), - }; - - return ( -
-
-
- {props.headings.map((heading, i) => ( -
- {heading} -
- ))} -
- {props.rows.map((row, i) => ( -
setSelectedRow(i)} - key={`row-${i}`} - > - {row.map((text, j) => ( -
- {text} -
- ))} -
- ))} -
-
-
- ); -} diff --git a/js/components/MediaLibraryWindow/TracksTable.tsx b/js/components/MediaLibraryWindow/TracksTable.tsx deleted file mode 100644 index a2221d19..00000000 --- a/js/components/MediaLibraryWindow/TracksTable.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import * as React from "react"; -import { connect } from "react-redux"; -import * as Selectors from "../../selectors"; -import { AppState, PlaylistTrack } from "../../types"; -import * as Utils from "../../utils"; -import * as FileUtils from "../../fileUtils"; -import LibraryTable from "./LibraryTable"; - -interface StateProps { - tracks: PlaylistTrack[]; - filterTracks: (query: string) => PlaylistTrack[]; -} - -interface State { - filter: string; -} - -class TracksTable extends React.Component { - constructor(props: StateProps) { - super(props); - this.state = { filter: "" }; - } - - render() { - return ( -
-
- Search: - this.setState({ filter: e.target.value })} - /> -
- { - return [ - track.artist, - track.title, - track.album, - Utils.getTimeStr(track.duration), - 1, - "Primus", - 2001, - track.url == null - ? track.defaultName - : FileUtils.filenameFromUrl(track.url), - ]; - })} - widths={[100, 100, 100, 100, 100, 100, 100, 100]} - /> - -
- - 1 item [3:25] - -
-
- ); - } -} - -const mapStateToProps = (state: AppState): StateProps => { - return { - tracks: Object.values(Selectors.getTracks(state)), - filterTracks: Selectors.getTracksMatchingFilter(state), - }; -}; - -export default connect(mapStateToProps)(TracksTable); diff --git a/js/components/MediaLibraryWindow/index.tsx b/js/components/MediaLibraryWindow/index.tsx index 66c5a2e5..b926c015 100644 --- a/js/components/MediaLibraryWindow/index.tsx +++ b/js/components/MediaLibraryWindow/index.tsx @@ -1,7 +1,4 @@ import * as React from "react"; -import ArtistsTable from "./ArtistsTable"; -import AlbumsTable from "./AlbumsTable"; -import TracksTable from "./TracksTable"; import LibraryLayout from "./LibraryLayout"; export default class MediaLibraryWindow extends React.Component<{}> { @@ -9,9 +6,9 @@ export default class MediaLibraryWindow extends React.Component<{}> { return ( } - albums={} - tracks={} + artists={null} + albums={null} + tracks={null} /> ); } diff --git a/js/selectors.ts b/js/selectors.ts index 76dbc2a0..01ecdbe6 100644 --- a/js/selectors.ts +++ b/js/selectors.ts @@ -30,7 +30,6 @@ import * as fromDisplay from "./reducers/display"; import * as fromEqualizer from "./reducers/equalizer"; import * as fromMedia from "./reducers/media"; import * as fromWindows from "./reducers/windows"; -import * as TrackUtils from "./trackUtils"; import * as MarqueeUtils from "./marqueeUtils"; import { generateGraph } from "./resizeUtils"; import { SerializedStateV1 } from "./serializedStates/v1Types"; @@ -53,17 +52,6 @@ export const getEqfData = createSelector(getSliders, sliders => { }); export const getTracks = (state: AppState) => state.tracks; - -export const getTracksMatchingFilter = createSelector(getTracks, tracks => { - const tracksArray = Object.values(tracks); - const filter = Utils.makeCachingFilterFunction(tracksArray, (track, query) => - TrackUtils.trackFilterContents(track).includes(query) - ); - return (filterString: string): PlaylistTrack[] => { - return filter(filterString.toLowerCase()); - }; -}); - export const getTrackUrl = (state: AppState) => { return (id: number): string | null => { return state.tracks[id]?.url; diff --git a/js/trackUtils.ts b/js/trackUtils.ts index 2f41a831..5559a2a4 100644 --- a/js/trackUtils.ts +++ b/js/trackUtils.ts @@ -35,12 +35,3 @@ export const trackFilename = Utils.weakMapMemoize( return "???"; } ); - -export const trackFilterContents = Utils.weakMapMemoize( - (track: PlaylistTrack): string => { - return [track.artist, track.title, track.defaultName] - .filter(Boolean) - .join("|") - .toLowerCase(); - } -); diff --git a/js/utils.test.ts b/js/utils.test.ts index 8f26ff2f..e19dffe9 100644 --- a/js/utils.test.ts +++ b/js/utils.test.ts @@ -11,7 +11,6 @@ import { segment, moveSelected, spliceIn, - makeCachingFilterFunction, replaceAtIndex, } from "./utils"; @@ -381,92 +380,6 @@ describe("spliceIn", () => { }); }); -describe("makeCachingFilterFunction", () => { - test("caches exact queries", () => { - const values = ["abc", "b", "c"]; - const includes = jest.fn((v, query) => v.includes(query)); - const filter = makeCachingFilterFunction(values, includes); - expect(filter("c")).toEqual(["abc", "c"]); - expect(includes.mock.calls.length).toBe(3); - expect(filter("c")).toEqual(["abc", "c"]); - expect(includes.mock.calls.length).toBe(3); - }); - - test("caches sub queries", () => { - const values = ["a--", "ab-", "abc"]; - const includes = jest.fn((v, query) => v.includes(query)); - let comparisons = 0; - const newComparisons = () => { - const recent = includes.mock.calls.length - comparisons; - comparisons += recent; - return recent; - }; - const filter = makeCachingFilterFunction(values, includes); - // Intial search - expect(filter("ab")).toEqual(["ab-", "abc"]); - expect(newComparisons()).toBe(3); // Looks at all elements - - // Second search where original search is a prefix - expect(filter("abc")).toEqual(["abc"]); - expect(newComparisons()).toBe(2); // Only reconsiders the previous matches - - // Unique search - expect(filter("b")).toEqual(["ab-", "abc"]); // Looks at all elements - expect(newComparisons()).toBe(3); // Reconsiders all elements - - expect(filter("bc")).toEqual(["abc"]); // Only reconsidres the matches that already include `b` - expect(newComparisons()).toBe(2); - - // Go back to the initial serach - expect(filter("ab")).toEqual(["ab-", "abc"]); - expect(newComparisons()).toBe(0); // Result is cached - - // A variation on the second search - expect(filter("abcd")).toEqual([]); - expect(newComparisons()).toBe(1); // Only recondsiders the results of `abc` - }); - - test("big data", () => { - const values = [...Array(10000)].map((val, i) => String(i)); - const includes = jest.fn((v, query) => v.includes(query)); - let comparisons = 0; - const newComparisons = () => { - const recent = includes.mock.calls.length - comparisons; - comparisons += recent; - return recent; - }; - const filter = makeCachingFilterFunction(values, includes); - // Intial search - expect(filter("").length).toEqual(10000); - expect(newComparisons()).toBe(0); // Looks at zero - - expect(filter("1").length).toEqual(3439); - expect(newComparisons()).toBe(10000); // Looks at all elements - - expect(filter("12").length).toEqual(299); - expect(newComparisons()).toBe(3439); - - expect(filter("123").length).toEqual(20); - expect(newComparisons()).toBe(299); - - expect(filter("1234").length).toEqual(1); - expect(newComparisons()).toBe(20); - - expect(filter("12345").length).toEqual(0); - expect(newComparisons()).toBe(1); - - // A variation on the initial non-empty query - expect(filter("11").length).toEqual(280); - expect(newComparisons()).toBe(3439); - - expect(filter("111").length).toEqual(19); - expect(newComparisons()).toBe(280); - - expect(filter("1111").length).toEqual(1); - expect(newComparisons()).toBe(19); - }); -}); - describe("replaceAtIndex", () => { test("can replace", () => { expect(replaceAtIndex([1, 2, 3, 4], 2, 0)).toEqual([1, 2, 0, 4]); diff --git a/js/utils.ts b/js/utils.ts index 438b0dd2..c9bdfcf0 100644 --- a/js/utils.ts +++ b/js/utils.ts @@ -403,39 +403,3 @@ export function weakMapMemoize( return cache.get(value); }; } - -interface Cache { - results?: V[]; - subCaches: { [char: string]: Cache }; -} - -// Is this a premature optimizaiton? Probably. But it's my side-project so I can -// do what I like. :P -export function makeCachingFilterFunction( - values: V[], - includes: (v: V, query: string) => boolean -) { - const cache: Cache = { - results: values, - subCaches: {}, - }; - return (query: string): V[] => { - let queryCache: Cache = cache; - let lastResults: V[] = values; - for (const char of query) { - let letterCaches = queryCache.subCaches[char]; - if (!letterCaches) { - letterCaches = queryCache.subCaches[char] = { subCaches: {} }; - } else if (letterCaches.results) { - lastResults = letterCaches.results; - } - queryCache = letterCaches; - } - - if (!queryCache.results) { - queryCache.results = lastResults.filter(v => includes(v, query)); - } - - return queryCache.results; - }; -}