Skip to content
This repository has been archived by the owner on Oct 18, 2024. It is now read-only.

Commit

Permalink
Merge pull request #116 from goosewobbler/0.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
goosewobbler authored Feb 15, 2022
2 parents bd14edd + 0e5d468 commit 78c811f
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 8 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "dj-helper",
"description": "A tool for constructing DJ sets",
"version": "0.1.4",
"version": "0.1.5",
"author": "Sam Maister <[email protected]>",
"license": "AGPL-3.0-or-later",
"main": "./bundle/main.prod.js",
Expand Down
3 changes: 3 additions & 0 deletions src/common/reduxStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ import offlineConfig from '@redux-offline/redux-offline/lib/defaults';
import ElectronStore from 'electron-store';
import { rootReducer, storeHydrated } from '../features/rootReducer';
import { AnyObject, AppStore } from './types';
import { log } from '../main/helpers/console';

function createElectronStorage() {
const store = new ElectronStore({});

log(`loading config from ${store.path}...`);

return {
getItem: (key: string) => Promise.resolve(store.get(key)),
setItem: (key: string, item: string) => Promise.resolve(store.set(key, item)),
Expand Down
26 changes: 24 additions & 2 deletions src/features/embed/embedSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const slice = createSlice({
case EmbedStatus.Loaded:
case EmbedStatus.Idle:
case EmbedStatus.Paused:
case EmbedStatus.PlayRequested:
case EmbedStatus.Playing:
return { ...state, trackId, loadContext: context, status: EmbedStatus.LoadRequested };
default:
Expand Down Expand Up @@ -75,6 +76,22 @@ export const slice = createSlice({

return state;
},
mediaPlaybackError: (state) => {
log('media playback error');
if ([EmbedStatus.PauseRequested, EmbedStatus.PlayRequested, EmbedStatus.Playing].includes(state.status)) {
return { ...state, status: EmbedStatus.Loaded };
}

return state;
},
mediaLoadError: (state) => {
log('media load error');
if ([EmbedStatus.LoadRequested].includes(state.status)) {
return { ...state, status: EmbedStatus.Idle };
}

return state;
},
autoplayEnabledToggled: (state, { payload: autoplayEnabled }: { payload: Embed['autoplayEnabled'] }) => ({
...state,
autoplayEnabled,
Expand All @@ -90,6 +107,8 @@ export const {
mediaPlaying,
requestPause,
mediaPaused,
mediaLoadError,
mediaPlaybackError,
autoplayEnabledToggled,
reset,
} = slice.actions;
Expand Down Expand Up @@ -281,10 +300,13 @@ export const trackIsLoaded =
embed.trackId === trackId;

export const embedRequestInFlight =
() =>
({ trackId }: { trackId: Track['id'] }) =>
({ embed }: AppState): boolean => {
log('embedRequestInFlight', embed);
return [EmbedStatus.LoadRequested, EmbedStatus.PauseRequested, EmbedStatus.PlayRequested].includes(embed.status);
return (
[EmbedStatus.LoadRequested, EmbedStatus.PauseRequested, EmbedStatus.PlayRequested].includes(embed.status) &&
embed.trackId === trackId
);
};

export const embedReducer = slice.reducer;
6 changes: 3 additions & 3 deletions src/features/tracks/BaseTrack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function BaseTrack({
const dispatch = useAppDispatch();
const track = useAppSelector(selectTrackById(id));
const isPlaying = useAppSelector(trackIsPlaying({ trackId: id }));
const showSpinner = useAppSelector(embedRequestInFlight());
const showSpinner = useAppSelector(embedRequestInFlight({ trackId: id }));

if (!track) {
return <> </>;
Expand All @@ -41,8 +41,8 @@ export function BaseTrack({
<span className="inline-block w-6/12 overflow-hidden whitespace-nowrap overflow-ellipsis">{title}</span>
<span className="inline-block w-1/12 overflow-hidden whitespace-nowrap">{displayTrackDuration(duration)}</span>
<span className="relative inline-block w-2/12 font-serif align-middle opacity-0 bottom-1 group-track-hover:opacity-100">
<span className="mx-2">{additionalButtons}</span>
<span className="float-left">
<span className="">{additionalButtons}</span>
<span className="float-left mx-2">
<PlayPauseButton
isPlaying={isPlaying}
showSpinner={showSpinner}
Expand Down
42 changes: 40 additions & 2 deletions src/main/trackEmbed.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { BrowserView, BrowserWindow, ipcMain } from 'electron';
import { platform } from 'os';
import { mediaLoaded, mediaPlaying, mediaPaused } from '../features/embed/embedSlice';
import {
mediaLoaded,
mediaPlaying,
mediaPaused,
mediaPlaybackError,
mediaLoadError,
} from '../features/embed/embedSlice';
import { AppStore, Track, TrackPreviewEmbedSize } from '../common/types';
import { log } from './helpers/console';
import { selectTrackSourceByIndex } from '../features/tracks/tracksSlice';
Expand All @@ -12,6 +18,8 @@ import { sanitiseUrl } from './browser';

let embed: BrowserView;
let lastClickPlayTime: number;
let playTimeout: NodeJS.Timeout;
let loadTimeout: NodeJS.Timeout;

export function initEmbed(mainWindow: BrowserWindow, reduxStore: AppStore): void {
const { dispatch, getState } = reduxStore;
Expand Down Expand Up @@ -42,7 +50,7 @@ export function initEmbed(mainWindow: BrowserWindow, reduxStore: AppStore): void
});

const trigger = async (toTrigger: string) => {
const isPlaying = !!(await embed.webContents.executeJavaScript('$("#player").hasClass("playing");', true));
let isPlaying = !!(await embed.webContents.executeJavaScript('$("#player").hasClass("playing");', true));
const canClick = (!isPlaying && toTrigger === 'play') || (isPlaying && toTrigger === 'pause');
log(`trigger ${toTrigger}`, isPlaying, canClick);
if (canClick) {
Expand All @@ -51,17 +59,42 @@ export function initEmbed(mainWindow: BrowserWindow, reduxStore: AppStore): void
log('clicked', Date.now());
if (toTrigger === 'play') {
lastClickPlayTime = Date.now();
setTimeout(() => {
void (async () => {
isPlaying = !!(await embed.webContents.executeJavaScript('$("#player").hasClass("playing");', true));
if (!isPlaying) {
log('second click incoming');
log('clicking', Date.now());
await embed.webContents.executeJavaScript('$("#big_play_button").click().length;', true);
log('clicked', Date.now());
}
})();
}, 300);

clearTimeout(playTimeout);
playTimeout = setTimeout(() => {
void (async () => {
isPlaying = !!(await embed.webContents.executeJavaScript('$("#player").hasClass("playing");', true));
if (!isPlaying) {
dispatch(mediaPlaybackError());
// TODO: update status panel
}
})();
}, 30000);
}
}
};

const mediaStartedPlayingHandler = () => {
clearTimeout(playTimeout);
log('playing from embed', Date.now());
dispatch(mediaPlaying());
};

const mediaPausedHandler = () => {
void (async () => {
clearTimeout(playTimeout);

const playbackComplete = (await embed.webContents.executeJavaScript('window.playbackComplete', true)) as boolean;
const currentTime = (await embed.webContents.executeJavaScript('$("#currenttime").text();', true)) as string;
const pausedByTrackEnding = currentTime === '00:00' && playbackComplete;
Expand Down Expand Up @@ -99,6 +132,7 @@ export function initEmbed(mainWindow: BrowserWindow, reduxStore: AppStore): void
}
const loadFinishedHandler = () => {
void (async () => {
clearTimeout(loadTimeout);
log('loaded', Date.now());
dispatch(mediaLoaded());
await embed.webContents.executeJavaScript(
Expand All @@ -116,6 +150,10 @@ export function initEmbed(mainWindow: BrowserWindow, reduxStore: AppStore): void
const embedSize = trackPreviewEmbedSize.toLowerCase();
const trackUrl = `https://bandcamp.com/EmbeddedPlayer/size=${embedSize}/bgcol=ffffff/linkcol=0687f5/track=${trackSource.sourceId}/transparent=true/`;
void embed.webContents.loadURL(trackUrl);
loadTimeout = setTimeout(() => {
dispatch(mediaLoadError());
// TODO: update status panel
}, 30000);
setBounds(trackPreviewEmbedSize);
}),
);
Expand Down

0 comments on commit 78c811f

Please sign in to comment.