mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-21 09:09:01 +00:00
Type Selectors
This commit is contained in:
parent
be3b024b0b
commit
bbf56232c3
4 changed files with 69 additions and 40 deletions
|
|
@ -271,8 +271,11 @@ export default playlist;
|
|||
|
||||
export const getTrackDisplayName = (
|
||||
state: PlaylistState,
|
||||
id: number
|
||||
id: number | null = null
|
||||
): string | null => {
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
const track = state.tracks[id];
|
||||
if (track == null) {
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { AppState, PlaylistTrack, WebampWindow, WindowId } from "./types";
|
||||
import { createSelector } from "reselect";
|
||||
import {
|
||||
denormalize,
|
||||
|
|
@ -18,10 +19,10 @@ import * as fromPlaylist from "./reducers/playlist";
|
|||
import * as fromDisplay from "./reducers/display";
|
||||
import { generateGraph } from "./resizeUtils";
|
||||
|
||||
export const getSliders = state => state.equalizer.sliders;
|
||||
export const getSliders = (state: AppState) => state.equalizer.sliders;
|
||||
|
||||
export const getEqfData = createSelector(getSliders, sliders => {
|
||||
const preset = {
|
||||
const preset: { [key: string]: number | string } = {
|
||||
name: "Entry1",
|
||||
preamp: denormalize(sliders.preamp)
|
||||
};
|
||||
|
|
@ -35,8 +36,8 @@ export const getEqfData = createSelector(getSliders, sliders => {
|
|||
return eqfData;
|
||||
});
|
||||
|
||||
export const getTracks = state => state.playlist.tracks;
|
||||
const getTrackOrder = state => state.playlist.trackOrder;
|
||||
export const getTracks = (state: AppState) => state.playlist.tracks;
|
||||
const getTrackOrder = (state: AppState) => state.playlist.trackOrder;
|
||||
|
||||
export const getTrackCount = createSelector(
|
||||
getTrackOrder,
|
||||
|
|
@ -52,7 +53,7 @@ export const getOrderedTracks = createSelector(
|
|||
const getOrderedTrackObjects = createSelector(
|
||||
getTracks,
|
||||
getOrderedTracks,
|
||||
(tracks, trackOrder) => trackOrder.map(id => tracks[id])
|
||||
(tracks, trackOrder): PlaylistTrack[] => trackOrder.map(id => tracks[id])
|
||||
);
|
||||
|
||||
export const getSelectedTrackObjects = createSelector(
|
||||
|
|
@ -61,7 +62,7 @@ export const getSelectedTrackObjects = createSelector(
|
|||
);
|
||||
|
||||
// If a duration is `null`, it counts as zero, which seems fine enough.
|
||||
const runningTimeFromTracks = tracks =>
|
||||
const runningTimeFromTracks = (tracks: PlaylistTrack[]) =>
|
||||
tracks.reduce((time, track) => time + Number(track.duration), 0);
|
||||
|
||||
const getTotalRunningTime = createSelector(
|
||||
|
|
@ -83,17 +84,23 @@ export const getRunningTimeMessage = createSelector(
|
|||
);
|
||||
|
||||
// TODO: use slectors to get memoization
|
||||
export const getCurrentTrackIndex = state =>
|
||||
state.playlist.trackOrder.indexOf(state.playlist.currentTrack);
|
||||
export const getCurrentTrackIndex = (state: AppState): number => {
|
||||
const { playlist } = state;
|
||||
if (playlist.currentTrack == null) {
|
||||
return -1;
|
||||
}
|
||||
return playlist.trackOrder.indexOf(playlist.currentTrack);
|
||||
};
|
||||
|
||||
export const getCurrentTrackNumber = createSelector(
|
||||
getCurrentTrackIndex,
|
||||
currentTrackIndex => currentTrackIndex + 1
|
||||
);
|
||||
|
||||
export const getCurrentTrackId = state => state.playlist.currentTrack;
|
||||
export const getCurrentTrackId = (state: AppState) =>
|
||||
state.playlist.currentTrack;
|
||||
|
||||
export const nextTrack = (state, n = 1) => {
|
||||
export const nextTrack = (state: AppState, n = 1) => {
|
||||
const {
|
||||
playlist: { trackOrder },
|
||||
media: { repeat }
|
||||
|
|
@ -126,7 +133,7 @@ export const nextTrack = (state, n = 1) => {
|
|||
};
|
||||
|
||||
const BASE_WINDOW_HEIGHT = 58;
|
||||
export const getNumberOfVisibleTracks = state => {
|
||||
export const getNumberOfVisibleTracks = (state: AppState) => {
|
||||
const playlistSize = getWindowSize(state, "playlist");
|
||||
return Math.floor(
|
||||
(BASE_WINDOW_HEIGHT + WINDOW_RESIZE_SEGMENT_HEIGHT * playlistSize[1]) /
|
||||
|
|
@ -141,7 +148,7 @@ export const getOverflowTrackCount = createSelector(
|
|||
Math.max(0, trackCount - numberOfVisibleTracks)
|
||||
);
|
||||
|
||||
const _getPlaylistScrollPosition = state =>
|
||||
const _getPlaylistScrollPosition = (state: AppState) =>
|
||||
state.display.playlistScrollPosition;
|
||||
|
||||
export const getPlaylistScrollPosition = createSelector(
|
||||
|
|
@ -180,7 +187,7 @@ export const getVisibleTrackIds = createSelector(
|
|||
export const getTrackIsVisibleFunction = createSelector(
|
||||
getVisibleTrackIds,
|
||||
visibleTrackIds => {
|
||||
return id => visibleTrackIds.includes(id);
|
||||
return (id: number) => visibleTrackIds.includes(id);
|
||||
}
|
||||
);
|
||||
|
||||
|
|
@ -190,17 +197,21 @@ export const getVisibleTracks = createSelector(
|
|||
(visibleTrackIds, tracks) => visibleTrackIds.map(id => tracks[id])
|
||||
);
|
||||
|
||||
export const getPlaylist = state => state.playlist;
|
||||
export const getPlaylist = (state: AppState) => state.playlist;
|
||||
|
||||
export const getDuration = state => {
|
||||
const currentTrack = state.playlist.tracks[state.playlist.currentTrack];
|
||||
export const getDuration = (state: AppState): number | null => {
|
||||
const { playlist } = state;
|
||||
if (playlist.currentTrack == null) {
|
||||
return null;
|
||||
}
|
||||
const currentTrack = playlist.tracks[playlist.currentTrack];
|
||||
return currentTrack && currentTrack.duration;
|
||||
};
|
||||
|
||||
export const getTrackDisplayName = (state, trackId) =>
|
||||
export const getTrackDisplayName = (state: AppState, trackId: number | null) =>
|
||||
fromPlaylist.getTrackDisplayName(getPlaylist(state), trackId);
|
||||
|
||||
export const getCurrentTrackDisplayName = state => {
|
||||
export const getCurrentTrackDisplayName = (state: AppState) => {
|
||||
const id = getCurrentTrackId(state);
|
||||
return getTrackDisplayName(state, id);
|
||||
};
|
||||
|
|
@ -221,9 +232,13 @@ export const getMediaText = createSelector(
|
|||
`${minimalMediaText} (${getTimeStr(duration)}) *** `
|
||||
);
|
||||
|
||||
export const getNumberOfTracks = state => getTrackOrder(state).length;
|
||||
export const getNumberOfTracks = (state: AppState) =>
|
||||
getTrackOrder(state).length;
|
||||
const getPlaylistDuration = createSelector(getTracks, tracks =>
|
||||
Object.values(tracks).reduce((total, track) => total + track.duration, 0)
|
||||
Object.values(tracks).reduce(
|
||||
(total, track) => total + (track.duration || 0),
|
||||
0
|
||||
)
|
||||
);
|
||||
|
||||
export const getPlaylistURL = createSelector(
|
||||
|
|
@ -248,14 +263,14 @@ export const getPlaylistURL = createSelector(
|
|||
})
|
||||
);
|
||||
|
||||
export function getWindowPositions(state) {
|
||||
export function getWindowPositions(state: AppState) {
|
||||
return state.windows.positions;
|
||||
}
|
||||
|
||||
const WINDOW_HEIGHT = 116;
|
||||
const SHADE_WINDOW_HEIGHT = 14;
|
||||
|
||||
function getWPixelSize(w, doubled) {
|
||||
function getWPixelSize(w: WebampWindow, doubled: boolean) {
|
||||
const [width, height] = w.size;
|
||||
const doubledMultiplier = doubled && w.canDouble ? 2 : 1;
|
||||
const pix = {
|
||||
|
|
@ -268,27 +283,27 @@ function getWPixelSize(w, doubled) {
|
|||
};
|
||||
}
|
||||
|
||||
export function getWindowSize(state, windowId) {
|
||||
export function getWindowSize(state: AppState, windowId: WindowId) {
|
||||
return state.windows.genWindows[windowId].size;
|
||||
}
|
||||
|
||||
export function getWindowOpen(state) {
|
||||
return windowId => state.windows.genWindows[windowId].open;
|
||||
export function getWindowOpen(state: AppState) {
|
||||
return (windowId: WindowId) => state.windows.genWindows[windowId].open;
|
||||
}
|
||||
|
||||
export function getWindowShade(state, windowId) {
|
||||
export function getWindowShade(state: AppState, windowId: WindowId) {
|
||||
return state.windows.genWindows[windowId].shade;
|
||||
}
|
||||
|
||||
export function getWindowHidden(state) {
|
||||
return windowId => state.windows.genWindows[windowId].hidden;
|
||||
export function getWindowHidden(state: AppState) {
|
||||
return (windowId: WindowId) => state.windows.genWindows[windowId].hidden;
|
||||
}
|
||||
|
||||
export const getGenWindows = state => {
|
||||
export const getGenWindows = (state: AppState) => {
|
||||
return state.windows.genWindows;
|
||||
};
|
||||
|
||||
export function getDoubled(state) {
|
||||
export function getDoubled(state: AppState) {
|
||||
return state.display.doubled;
|
||||
}
|
||||
|
||||
|
|
@ -300,7 +315,7 @@ export const getWindowSizes = createSelector(
|
|||
}
|
||||
);
|
||||
|
||||
export function getWindowPixelSize(state, windowId) {
|
||||
export function getWindowPixelSize(state: AppState, windowId: WindowId) {
|
||||
// Rather than compute it directly, we go via `getWindowSizes`
|
||||
// to take advantage of caching.
|
||||
return getWindowSizes(state)[windowId];
|
||||
|
|
@ -315,7 +330,7 @@ export const getWindowsInfo = createSelector(
|
|||
|
||||
export const getWindowGraph = createSelector(getWindowsInfo, generateGraph);
|
||||
|
||||
export const getSkinPlaylistStyle = state => {
|
||||
export const getSkinPlaylistStyle = (state: AppState) => {
|
||||
return (
|
||||
state.display.skinPlaylistStyle || {
|
||||
normal: "#00FF00",
|
||||
|
|
@ -327,5 +342,5 @@ export const getSkinPlaylistStyle = state => {
|
|||
);
|
||||
};
|
||||
|
||||
export const getVisualizerStyle = state =>
|
||||
export const getVisualizerStyle = (state: AppState) =>
|
||||
fromDisplay.getVisualizerStyle(state.display);
|
||||
18
js/types.ts
18
js/types.ts
|
|
@ -31,7 +31,7 @@ type SkinImages = { [sprite: string]: string };
|
|||
// TODO: type these keys
|
||||
type SkinRegion = { [windowName: string]: string[] };
|
||||
|
||||
type WindowId = string;
|
||||
export type WindowId = string;
|
||||
|
||||
// TODO: Fill these out once we actually use them.
|
||||
type SkinData = {
|
||||
|
|
@ -43,6 +43,13 @@ type SkinData = {
|
|||
skinGenLetterWidths: GenLetterWidths;
|
||||
};
|
||||
|
||||
interface WindowPosition {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
export type WindowPositions = {
|
||||
[windowId: string]: WindowPosition;
|
||||
};
|
||||
export type Action =
|
||||
| {
|
||||
type: "NETWORK_CONNECTED";
|
||||
|
|
@ -232,7 +239,7 @@ export type Action =
|
|||
}
|
||||
| {
|
||||
type: "UPDATE_WINDOW_POSITIONS";
|
||||
positions: {};
|
||||
positions: WindowPositions;
|
||||
}
|
||||
| {
|
||||
type: "CLICKED_TRACK";
|
||||
|
|
@ -361,7 +368,7 @@ export interface EqualizerState {
|
|||
sliders: Record<Slider, number>;
|
||||
}
|
||||
|
||||
export interface Window {
|
||||
export interface WebampWindow {
|
||||
title: string;
|
||||
size: [number, number];
|
||||
open: boolean;
|
||||
|
|
@ -376,8 +383,8 @@ export interface Window {
|
|||
|
||||
export interface WindowState {
|
||||
focused: string;
|
||||
genWindows: { [name: string]: Window };
|
||||
positions: {}; // TODO: Make this more strict
|
||||
genWindows: { [name: string]: WebampWindow };
|
||||
positions: WindowPositions;
|
||||
}
|
||||
|
||||
export type MediaTagRequestStatus =
|
||||
|
|
@ -394,6 +401,7 @@ export interface PlaylistTrack {
|
|||
albumArtUrl: string | null;
|
||||
selected: boolean;
|
||||
mediaTagsRequestStatus: MediaTagRequestStatus;
|
||||
duration: number | null;
|
||||
}
|
||||
|
||||
export interface PlaylistState {
|
||||
|
|
|
|||
|
|
@ -51,7 +51,10 @@ export const getTimeObj = (time: number | null): Time => {
|
|||
};
|
||||
};
|
||||
|
||||
export const getTimeStr = (time: number, truncate: boolean = true): string => {
|
||||
export const getTimeStr = (
|
||||
time: number | null,
|
||||
truncate: boolean = true
|
||||
): string => {
|
||||
if (time == null) {
|
||||
return "";
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue