Skip to content
8 changes: 4 additions & 4 deletions src/main/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export const getAuthUrl = (): string => {
const scopes = AUTH_SCOPES.join('%20');

const authUrl =
`${AUTH_URL}?response_type=code&client_id=${AUTH_CLIENT_ID}&redirect_uri=http://localhost:${AUTH_PORT}&` +
`${AUTH_URL}?response_type=code&client_id=${AUTH_CLIENT_ID}&redirect_uri=http://127.0.0.1:${AUTH_PORT}&` +
`scope=${scopes}&state=${codeState}&code_challenge=${codeChallenge}&code_challenge_method=S256`;

return authUrl;
Expand Down Expand Up @@ -104,7 +104,7 @@ export const refreshAccessToken = async (refreshToken: string): Promise<void> =>
data = null;
} else if (!scopesMatch(data.scope)) {
console.warn(
`Authorization scopes mismatch\n Expected: ${AUTH_SCOPES.join(' ')}\n Token has: '${data.scope}`
`Authorization scopes mismatch\n Expected: ${AUTH_SCOPES.join(' ')}\n Token has: '${data.scope}'`
);
data = null;
} else {
Expand All @@ -120,7 +120,7 @@ const retrieveAccessToken = async (verifier: string, code: string): Promise<Auth

const body =
`client_id=${AUTH_CLIENT_ID}&grant_type=authorization_code&` +
`code=${code}&redirect_uri=http://localhost:${AUTH_PORT}&code_verifier=${verifier}`;
`code=${code}&redirect_uri=http://127.0.0.1:${AUTH_PORT}&code_verifier=${verifier}`;

const res = await fetch(AUTH_TOKEN_URL, {
method: 'POST',
Expand Down Expand Up @@ -149,7 +149,7 @@ const stopServer = (): void => {
};

const handleServerResponse = async (request: http.IncomingMessage, response: http.ServerResponse): Promise<void> => {
const urlObj = new URL(`http://localhost:${AUTH_PORT}/${request.url}`);
const urlObj = new URL(`http://127.0.0.1:${AUTH_PORT}/${request.url}`);
const queryState = urlObj.searchParams.get('state');

try {
Expand Down
8 changes: 4 additions & 4 deletions src/renderer/api/spotify-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ class SpotifyApi {
private refreshToken: string;

async updateTokens(data: AuthData): Promise<SpotifyUserProfile> {
this.accessToken = data?.access_token;
this.refreshToken = data?.refresh_token;
this.accessToken = data?.access_token ?? this.accessToken;
this.refreshToken = data?.refresh_token ?? this.refreshToken;

if (!this.accessToken) {
return null;
Expand Down Expand Up @@ -119,13 +119,13 @@ class SpotifyApi {

async like(isLiked: boolean, trackId: string): Promise<void> {
const verb = isLiked ? 'DELETE' : 'PUT';
await this.fetch(`/me/tracks?ids=${trackId}`, {
await this.fetch(`/me/library?uris=spotify:track:${trackId}`, {
method: verb,
});
}

async isTrackLiked(trackId: string): Promise<boolean> {
const likedResponse: Array<boolean> = await this.fetch(`/me/tracks/contains?ids=${trackId}`, {
const likedResponse: Array<boolean> = await this.fetch(`/me/library/contains?uris=spotify:track:${trackId}`, {
method: 'GET',
});

Expand Down
54 changes: 36 additions & 18 deletions src/renderer/app/cover/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,9 @@ export const Cover: FunctionComponent<Props> = ({ settings, message, onVisualiza
setCurrentSongId(state.id);
console.log(`New song '${songTitle}' by '${artist}.`);
await refreshTrackLiked();
}

if (!isAlwaysShowTrackInfo && showTrackInfoTemporarilyInSeconds) {
} else if (!isAlwaysShowTrackInfo && showTrackInfoTemporarilyInSeconds) {
setShouldShowTrackInfo(true);
console.log('Showing track info temporarily.');

const timer = setTimeout(() => {
if (!document.getElementById('visible-ui')?.matches(':hover')) {
Expand All @@ -143,12 +142,12 @@ export const Cover: FunctionComponent<Props> = ({ settings, message, onVisualiza
]);

useEffect(() => {
return () => {
if (trackInfoTimer) {
clearTimeout(trackInfoTimer);
}
};
}, [trackInfoTimer]);
if (!state.isPlaying && trackInfoTimer) {
clearTimeout(trackInfoTimer);
setTrackInfoTimer(null);
setShouldShowTrackInfo(false);
}
}, [state.isPlaying, trackInfoTimer]);

const keepAlive = useCallback(async (): Promise<void> => {
if (state.isPlaying || state.userProfile?.accountType !== AccountType.Premium) {
Expand All @@ -166,6 +165,11 @@ export const Cover: FunctionComponent<Props> = ({ settings, message, onVisualiza
}
}, [state.isPlaying, state.progress, state.userProfile?.accountType]);

const [localVolume, setLocalVolume] = useState(state.volume);
useEffect(() => {
setLocalVolume(state.volume);
}, [state.volume]);

const changeVolume = useCallback(
(newVolume: number) => {
try {
Expand All @@ -191,27 +195,41 @@ export const Cover: FunctionComponent<Props> = ({ settings, message, onVisualiza

const onMouseWheel = useCallback(
async ({ deltaY }: WheelEvent): Promise<void> => {
const direction = Math.sign(deltaY);
const newVolume = clamp(state.volume - direction * volumeIncrement, 0, 100);
const direction = Math.sign(-deltaY);
console.log(`Mouse wheel direction: ${direction}`);
const newVolume = clamp(localVolume + volumeIncrement * direction, 0, 100);
setLocalVolume(newVolume);
try {
// TODO use a state variable to buffer the volume change
if (newVolume !== state.volume) {
changeVolume(newVolume);
}
changeVolume(newVolume);
} catch (error) {
throw new Error(`Update volume error: ${error}`);
}
},
[changeVolume, state.volume, volumeIncrement]
[localVolume, volumeIncrement, changeVolume]
);

const ondblClick = useCallback((): void => {
console.log('Double clicked');
// Add functionality here
// Tried opening spotify app but couldn't get it to work
}, []);

useEffect(() => {
document.getElementById('visible-ui').addEventListener('mousewheel', onMouseWheel);
const el = document.getElementById('visible-ui');
el.addEventListener('mousewheel', onMouseWheel);
return () => {
document.getElementById('visible-ui').removeEventListener('mousewheel', onMouseWheel);
el.removeEventListener('mousewheel', onMouseWheel);
};
}, [onMouseWheel]);

useEffect(() => {
const el = document.getElementById('visible-ui');
el.addEventListener('dblclick', ondblClick);
return () => {
el.removeEventListener('dblclick', ondblClick);
};
}, [ondblClick]);

useEffect(() => {
const listeningToIntervalId = setInterval(handlePlaybackChanged, trackInfoRefreshTimeInSeconds * ONE_SECOND_IN_MS);

Expand Down
2 changes: 1 addition & 1 deletion src/renderer/windows/settings/window-settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export const WindowSettings: FunctionComponent = () => {
<Slider
type="range"
min={0}
max={10}
max={15}
step={1}
defaultValue={DEFAULT_SETTINGS.showTrackInfoTemporarilyInSeconds}
{...register('showTrackInfoTemporarilyInSeconds', { required: true, valueAsNumber: true })}
Expand Down
8 changes: 2 additions & 6 deletions src/renderer/windows/track-info/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@ const TrackInfoWrapper = styled.div`

const Track = styled.div`
font-weight: bold;
padding: 0 0.25rem;
`;

const Artist = styled(Track)`
font-weight: normal;
font-size: 90%;
padding: 0 0.25rem;
`;

const MessageWrapper = styled.div`
Expand Down Expand Up @@ -76,25 +78,19 @@ export const TrackInfo: FunctionComponent<TrackInfoProps> = ({ track, artist, me
<Track
style={{
textAlign: isOnLeft ? 'start' : 'end',
paddingLeft: !isOnLeft && '0.5rem',
paddingRight: isOnLeft && '0.5rem',
}}>
{track}
</Track>
<Artist
style={{
textAlign: isOnLeft ? 'start' : 'end',
paddingLeft: !isOnLeft && '0.5rem',
paddingRight: isOnLeft && '0.5rem',
}}>
{artist}
</Artist>
<MessageWrapper
style={{
display: message ? 'flex' : 'none',
justifyContent: isOnLeft ? 'start' : 'end',
paddingLeft: !isOnLeft && '0.5rem',
paddingRight: isOnLeft && '0.5rem',
}}>
<i className="fa fa-warning" />
<Message>{message}</Message>
Expand Down