Skip to content

Commit

Permalink
Merge pull request #92 from simonv3/various-0-3-1-fixes
Browse files Browse the repository at this point in the history
WIP some more bug fixes, general playability.
  • Loading branch information
simonv3 authored Apr 27, 2022
2 parents 040524f + 5bf840c commit 3c0ed51
Show file tree
Hide file tree
Showing 10 changed files with 197 additions and 37 deletions.
35 changes: 23 additions & 12 deletions public/electron.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
// Module to control the application lifecycle and the native browser window.
const { app, BrowserWindow, nativeTheme, ipcMain, protocol, shell } = require("electron");
const {
app,
BrowserWindow,
nativeTheme,
ipcMain,
protocol,
shell,
} = require("electron");
const path = require("path");

// Create the native browser window.
Expand All @@ -16,12 +23,16 @@ function createWindow() {
icon: path.join(__dirname, "icons/256x256.png"),
});

const fileUrl = require("url").format({
protocol: "file",
slashes: true,
pathname: require("path").join(__dirname, "index.html"),
});

// In production, set the initial browser path to the local bundle generated
// by the Create React App build process.
// In development, set it to localhost to allow live/hot-reloading.
const appURL = app.isPackaged
? `file://${__dirname}/index.html`
: "http://localhost:8080";
const appURL = app.isPackaged ? fileUrl : "http://localhost:8080";
mainWindow.loadURL(appURL);

// Automatically open Chrome's DevTools in development mode.
Expand All @@ -30,18 +41,18 @@ function createWindow() {
}

// Dark mode
ipcMain.handle('dark-mode:toggle', () => {
ipcMain.handle("dark-mode:toggle", () => {
if (nativeTheme.shouldUseDarkColors) {
nativeTheme.themeSource = 'light'
nativeTheme.themeSource = "light";
} else {
nativeTheme.themeSource = 'dark'
nativeTheme.themeSource = "dark";
}
return nativeTheme.shouldUseDarkColors
})
return nativeTheme.shouldUseDarkColors;
});

ipcMain.handle('dark-mode:system', () => {
nativeTheme.themeSource = 'system'
})
ipcMain.handle("dark-mode:system", () => {
nativeTheme.themeSource = "system";
});
}

// Setup a local proxy to adjust the paths of requested files when loading
Expand Down
2 changes: 2 additions & 0 deletions src/components/ArtistPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ export const ArtistPage: React.FC = () => {
<div className={padding}>
<OverflowableText text={artist.bio} />
</div>
<p className={padding}>{artist.country}</p>

<p className={padding}>
{artist.links.map((link) => (
<LinkToWeb key={link.href} link={link} />
Expand Down
15 changes: 13 additions & 2 deletions src/components/Queue.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import TrackList from "./common/TrackList";
import EmptyBox from "./common/EmptyBox";
import { FullScreenSpinner } from "./common/Spinner";
import { determineNewTrackOrder } from "utils/tracks";
import { FaTrashAlt } from "react-icons/fa";

export const Queue: React.FC = () => {
const {
Expand Down Expand Up @@ -100,12 +101,22 @@ export const Queue: React.FC = () => {
`}
>
<h3>Queue</h3>
<div
className={css`
flex-grow: 1;
`}
/>
{!isLoading && playerQueue?.length > 0 && (
<>
<Button compact onClick={shuffleQueue} startIcon={<MdShuffle />}>
<Button
compact
onClick={shuffleQueue}
startIcon={<MdShuffle />}
style={{ marginRight: ".5rem" }}
>
Shuffle
</Button>
<Button compact onClick={clearQueue}>
<Button compact onClick={clearQueue} startIcon={<FaTrashAlt />}>
Clear queue
</Button>
</>
Expand Down
30 changes: 22 additions & 8 deletions src/components/common/ClickToPlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { useGlobalStateContext } from "../../contexts/globalState";
import { fetchTrackGroup } from "../../services/Api";
import Button from "./Button";
import ImageWithPlaceholder from "./ImageWithPlaceholder";
import { PlayingMusicBars } from "./PlayingMusicBars";

type WrapperProps = {
width: number;
Expand All @@ -36,7 +37,7 @@ const PlayWrapper = styled.div<WrapperProps>`
background-color: transparent;
font-size: 1rem;
&:nth-child(1) {
&:nth-of-type(1) {
margin-bottom: 0.5rem;
}
Expand Down Expand Up @@ -86,7 +87,8 @@ const ClickToPlay: React.FC<{
title: string;
image: ResonateImage;
className?: string;
}> = ({ groupId, title, image, trackId, className }) => {
playActionIntercept?: (trackId: number) => void;
}> = ({ groupId, title, image, trackId, className, playActionIntercept }) => {
const {
state: { playing, playerQueueIds },
dispatch,
Expand All @@ -99,19 +101,24 @@ const ClickToPlay: React.FC<{
const result = await fetchTrackGroup(groupId);
ids = result.items.map((item) => item.track.id);
} else if (trackId) {
if (playerQueueIds.includes(trackId)) {
const indexOfTrack = playerQueueIds.indexOf(trackId);
const newTracks = playerQueueIds.slice(indexOfTrack);
ids = [...newTracks];
if (playActionIntercept) {
playActionIntercept(trackId);
return;
} else {
ids = [trackId];
if (playerQueueIds.includes(trackId)) {
const indexOfTrack = playerQueueIds.indexOf(trackId);
const newTracks = playerQueueIds.slice(indexOfTrack);
ids = [...newTracks];
} else {
ids = [trackId];
}
}
}
dispatch({
type: "setValuesDirectly",
values: { playing: true, playerQueueIds: ids },
});
}, [dispatch, groupId, trackId, playerQueueIds]);
}, [dispatch, groupId, trackId, playerQueueIds, playActionIntercept]);

const onClickQueue = React.useCallback(async () => {
if (groupId) {
Expand Down Expand Up @@ -157,6 +164,13 @@ const ClickToPlay: React.FC<{
Queue
</Button>
</PlayWrapper>
{currentlyPlaying && (
<PlayingMusicBars
width={image?.width ?? 0}
height={image?.height ?? 0}
/>
)}

{image && (
<ImageWithPlaceholder src={image.url} alt={title} size={image.width} />
)}
Expand Down
83 changes: 83 additions & 0 deletions src/components/common/PlayingMusicBars.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import styled from "@emotion/styled";

type WrapperProps = {
width: number;
height: number;
};

const Wrapper = styled.div<WrapperProps>`
position: absolute;
bottom: 0;
right: 0;
left: 0;
top: 0;
display: flex;
align-items: center;
justify-content: center;
width: ${(props) => props.width}px;
height: ${(props) => props.height}px;
div {
justify-content: space-between;
height: 20px;
width: 20px;
display: flex;
}
@keyframes bounce {
10% {
transform: scaleY(0.3); /* start by scaling to 30% */
}
30% {
transform: scaleY(1); /* scale up to 100% */
}
60% {
transform: scaleY(0.5); /* scale down to 50% */
}
80% {
transform: scaleY(0.75); /* scale up to 75% */
}
100% {
transform: scaleY(0.6); /* scale down to 60% */
}
}
span {
width: 5px;
height: 100%;
background-color: var(--magenta);
border-radius: 3px;
transform-origin: bottom;
animation: bounce 2.2s ease infinite alternate;
content: "";
}
span {
&:nth-of-type(2) {
animation-delay: -2.2s; /* Start at the end of animation */
}
&:nth-of-type(3) {
animation-delay: -3.7s; /* Start mid-way of return of animation */
}
}
`;

export const PlayingMusicBars: React.FC<{ width: number; height: number }> = ({
width,
height,
}) => {
return (
<Wrapper width={width} height={height}>
<div>
<span />
<span />
<span />
</div>
</Wrapper>
);
};
2 changes: 1 addition & 1 deletion src/components/common/Spinner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const spinnerClass = css`
border-radius: 50%;
animation: lds-ripple 1s cubic-bezier(0, 0.2, 0.8, 1) infinite;
}
div:nth-child(2) {
div:nth-of-type(2) {
animation-delay: -0.5s;
}
@keyframes lds-ripple {
Expand Down
20 changes: 19 additions & 1 deletion src/components/common/TrackList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Link } from "react-router-dom";
import TrackPopup from "./TrackPopup";
import ResultListItem from "./ResultListItem";
import useDraggableTrack from "utils/useDraggableTrack";
import { useGlobalStateContext } from "contexts/globalState";

const staffPickUl = css``;

Expand All @@ -23,6 +24,20 @@ const TrackList: React.FC<{
...track,
key: `${track.id} + ${index}`,
}));
const { dispatch } = useGlobalStateContext();

const addTracksToQueue = React.useCallback(
(id: number) => {
const idx = tracks.findIndex((track) => track.id === id);
dispatch({
type: "setPlayerQueueIds",
playerQueueIds: tracks
.slice(idx, tracks.length)
.map((track) => track.id),
});
},
[dispatch, tracks]
);

return (
<>
Expand All @@ -34,6 +49,7 @@ const TrackList: React.FC<{
handleDrop={handleDrop}
draggable={draggable}
fullWidth={fullWidth}
addTracksToQueue={addTracksToQueue}
/>
))}
</ul>
Expand All @@ -46,7 +62,8 @@ const TrackLIWrapper: React.FC<{
handleDrop?: (ev: React.DragEvent<HTMLLIElement>) => void;
draggable?: boolean;
fullWidth?: boolean;
}> = ({ track, draggable, fullWidth, handleDrop }) => {
addTracksToQueue?: (id: number) => void;
}> = ({ track, draggable, fullWidth, handleDrop, addTracksToQueue }) => {
const { onDragStart, onDragEnd } = useDraggableTrack();

const [isHoveringOver, setIsHoveringOver] = React.useState(false);
Expand Down Expand Up @@ -85,6 +102,7 @@ const TrackLIWrapper: React.FC<{
trackId={track.id}
title={track.title}
image={track.images.small}
playActionIntercept={addTracksToQueue}
/>
)}
<SmallTileDetails
Expand Down
4 changes: 4 additions & 0 deletions src/contexts/globalState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ const stateReducer = produce((draft: GlobalState, action: Actions) => {
break;
}
case "clearQueue":
if (newDraft.playing) {
newDraft.playerQueueIds = [newDraft.playerQueueIds[0]];
break;
}
newDraft.playerQueueIds = [];
break;
case "setToken":
Expand Down
42 changes: 29 additions & 13 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,41 @@
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import { BrowserRouter, MemoryRouter } from "react-router-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { GlobalStateProvider } from "./contexts/globalState";
import * as serviceWorkerRegistration from "./serviceWorkerRegistration";
import { SnackBarContextProvider } from "contexts/SnackbarContext";

ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<SnackBarContextProvider>
<GlobalStateProvider>
<App />
</GlobalStateProvider>
</SnackBarContextProvider>
</BrowserRouter>
</React.StrictMode>,
document.getElementById("root")
);
var userAgent = navigator.userAgent.toLowerCase();
if (userAgent.indexOf(" electron/") > -1) {
ReactDOM.render(
<React.StrictMode>
<MemoryRouter>
<SnackBarContextProvider>
<GlobalStateProvider>
<App />
</GlobalStateProvider>
</SnackBarContextProvider>
</MemoryRouter>
</React.StrictMode>,
document.getElementById("root")
);
} else {
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<SnackBarContextProvider>
<GlobalStateProvider>
<App />
</GlobalStateProvider>
</SnackBarContextProvider>
</BrowserRouter>
</React.StrictMode>,
document.getElementById("root")
);
}

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
Expand Down
1 change: 1 addition & 0 deletions src/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ declare global {
}[];
images?: ArtistImage;
bio: string;
country: string;
}

interface Track {
Expand Down

0 comments on commit 3c0ed51

Please sign in to comment.