Skip to content

Commit

Permalink
Add mock ReplayService (#408)
Browse files Browse the repository at this point in the history
* add mock replay service

* fix binding of this issue

* try to avoid more binding issues

* fix replay usage
  • Loading branch information
vinceau authored Nov 19, 2023
1 parent 58206e7 commit 3a718a2
Show file tree
Hide file tree
Showing 16 changed files with 297 additions and 146 deletions.
2 changes: 1 addition & 1 deletion .erb/configs/webpack.config.renderer.dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ if (!requiredByDLLConfig && !(fs.existsSync(webpackPaths.dllPath) && fs.existsSy
execSync("yarn run postinstall");
}

const allMockableServices: readonly string[] = ["auth", "slippi", "dolphin"];
const allMockableServices: readonly string[] = ["auth", "slippi", "dolphin", "replay"];

const parseMockServices = (envString?: string | true): readonly string[] => {
if (envString === true) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,6 @@
"semver-regex": "^3.1.2",
"stun": "^2.1.0",
"wget-improved": "^3.3.1",
"zustand": "^3.2.0"
"zustand": "^4.4.6"
}
}
12 changes: 7 additions & 5 deletions src/renderer/containers/ReplayBrowser/FilterToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import IconButton from "@mui/material/IconButton";
import InputAdornment from "@mui/material/InputAdornment";
import InputBase from "@mui/material/InputBase";
import debounce from "lodash/debounce";
import React from "react";
import React, { useRef } from "react";

import { Button, Checkbox, Dropdown } from "@/components/FormInputs";
import { useReplayFilter } from "@/lib/hooks/useReplayFilter";
import { useReplays } from "@/lib/hooks/useReplays";
import { ReplayPresenter, useReplays } from "@/lib/hooks/useReplays";
import { useSettings } from "@/lib/hooks/useSettings";
import { useToasts } from "@/lib/hooks/useToasts";
import { ReplaySortOption, SortDirection } from "@/lib/replayFileSort";
import { useServices } from "@/services";

const Outer = styled.div`
display: flex;
Expand All @@ -34,8 +35,9 @@ type FilterToolbarProps = {
};

export const FilterToolbar = React.forwardRef<HTMLInputElement, FilterToolbarProps>((props, ref) => {
const { replayService } = useServices();
const presenter = useRef(new ReplayPresenter(replayService));
const { disabled } = props;
const init = useReplays((store) => store.init);
const rootSlpPath = useSettings((store) => store.settings.rootSlpPath);
const extraSlpPaths = useSettings((store) => store.settings.extraSlpPaths);
const currentFolder = useReplays((store) => store.currentFolder);
Expand All @@ -51,8 +53,8 @@ export const FilterToolbar = React.forwardRef<HTMLInputElement, FilterToolbarPro
const { showError } = useToasts();

const refresh = React.useCallback(() => {
init(rootSlpPath, extraSlpPaths, true, currentFolder).catch(showError);
}, [rootSlpPath, extraSlpPaths, init, currentFolder, showError]);
presenter.current.init(rootSlpPath, extraSlpPaths, true, currentFolder).catch(showError);
}, [rootSlpPath, extraSlpPaths, currentFolder, showError]);

const debounceChange = debounce((text: string) => {
setStoreSearchText(text);
Expand Down
24 changes: 10 additions & 14 deletions src/renderer/containers/ReplayBrowser/ReplayBrowser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { IconMessage } from "@/components/Message";
import { useDolphinActions } from "@/lib/dolphin/useDolphinActions";
import { useReplayBrowserList, useReplayBrowserNavigation } from "@/lib/hooks/useReplayBrowserList";
import { useReplayFilter } from "@/lib/hooks/useReplayFilter";
import { useReplays, useReplaySelection } from "@/lib/hooks/useReplays";
import { ReplayPresenter, useReplays, useReplaySelection } from "@/lib/hooks/useReplays";
import { useToasts } from "@/lib/hooks/useToasts";
import { humanReadableBytes } from "@/lib/utils";
import { useServices } from "@/services";
Expand All @@ -30,20 +30,16 @@ import { FilterToolbar } from "./FilterToolbar";
import { FolderTreeNode } from "./FolderTreeNode";

export const ReplayBrowser = React.memo(() => {
const { replayService } = useServices();
const presenter = React.useRef(new ReplayPresenter(replayService));
const searchInputRef = React.createRef<HTMLInputElement>();
const scrollRowItem = useReplays((store) => store.scrollRowItem);
const setScrollRowItem = useReplays((store) => store.setScrollRowItem);
const removeFiles = useReplays((store) => store.removeFiles);
const selectFile = useReplays((store) => store.selectFile);
const { dolphinService } = useServices();
const { viewReplays } = useDolphinActions(dolphinService);
const clearSelectedFile = useReplays((store) => store.clearSelectedFile);
const loading = useReplays((store) => store.loading);
const currentFolder = useReplays((store) => store.currentFolder);
const folderTree = useReplays((store) => store.folderTree);
const loadFolder = useReplays((store) => store.loadFolder);
const collapsedFolders = useReplays((store) => store.collapsedFolders);
const toggleFolder = useReplays((store) => store.toggleFolder);
const selectedFiles = useReplays((store) => store.selectedFiles);
const totalBytes = useReplays((store) => store.totalBytes);
const fileSelection = useReplaySelection();
Expand All @@ -56,16 +52,16 @@ export const ReplayBrowser = React.memo(() => {

const setSelectedItem = (index: number | null) => {
if (index === null) {
void clearSelectedFile();
void presenter.current.clearSelectedFile();
} else {
const file = filteredFiles[index];
void selectFile(file, index, filteredFiles.length);
void presenter.current.selectFile(file, index, filteredFiles.length);
goToReplayStatsPage(file.fullPath);
}
};

const onFolderTreeNodeClick = (fullPath: string) => {
loadFolder(fullPath).catch(showError);
presenter.current.loadFolder(fullPath).catch(showError);
};

const playSelectedFile = (index: number) => {
Expand All @@ -76,7 +72,7 @@ export const ReplayBrowser = React.memo(() => {
const deleteFiles = React.useCallback(
(filePaths: string[]) => {
// Optimistically remove the files first
removeFiles(filePaths);
presenter.current.removeFiles(filePaths);

window.electron.common
.deleteFiles(filePaths)
Expand All @@ -85,7 +81,7 @@ export const ReplayBrowser = React.memo(() => {
})
.catch(showError);
},
[showError, showSuccess, removeFiles],
[showError, showSuccess],
);

return (
Expand Down Expand Up @@ -114,7 +110,7 @@ export const ReplayBrowser = React.memo(() => {
key={folder.fullPath}
collapsedFolders={collapsedFolders}
onClick={onFolderTreeNodeClick}
onToggle={toggleFolder}
onToggle={(folder) => presenter.current.toggleFolder(folder)}
/>
);
})}
Expand Down Expand Up @@ -163,7 +159,7 @@ export const ReplayBrowser = React.memo(() => {
onPlay={(index: number) => playSelectedFile(index)}
files={filteredFiles}
scrollRowItem={scrollRowItem}
setScrollRowItem={setScrollRowItem}
setScrollRowItem={(item) => presenter.current.setScrollRowItem(item)}
/>
)}
<FileSelectionToolbar
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/containers/ReplayFileStats/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,15 @@ type ReplayFileStatsProps = {
export const ReplayFileStats = (props: ReplayFileStatsProps) => {
const { filePath } = props;

const { dolphinService } = useServices();
const { dolphinService, replayService } = useServices();
const { viewReplays } = useDolphinActions(dolphinService);
const gameStatsQuery = useQuery(["loadStatsQuery", filePath], async () => {
const result = await window.electron.replays.calculateGameStats(filePath);
const result = await replayService.calculateGameStats(filePath);
return result;
});

const stadiumStatsQuery = useQuery(["loadStadiumStatsQuery", filePath], async () => {
const result = await window.electron.replays.calculateStadiumStats(filePath);
const result = await replayService.calculateStadiumStats(filePath);
return result;
});

Expand Down
28 changes: 14 additions & 14 deletions src/renderer/lib/hooks/useAppListeners.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { IsoValidity } from "@common/types";
import type { Progress } from "@replays/types";
import log from "electron-log";
import throttle from "lodash/throttle";
import React from "react";
import React, { useRef } from "react";

import { useAppInitialization, useAppStore } from "@/lib/hooks/useApp";
import { useConsole } from "@/lib/hooks/useConsole";
import { useReplays } from "@/lib/hooks/useReplays";
import { ReplayPresenter } from "@/lib/hooks/useReplays";
import { useToasts } from "@/lib/hooks/useToasts";
import { useServices } from "@/services";

Expand All @@ -22,7 +23,8 @@ import { useSettingsModal } from "./useSettingsModal";

export const useAppListeners = () => {
// Handle app initalization
const { authService, broadcastService, consoleService, dolphinService } = useServices();
const { authService, broadcastService, consoleService, dolphinService, replayService } = useServices();
const replayPresenter = useRef(new ReplayPresenter(replayService));
const initialized = useAppStore((store) => store.initialized);
const initializeApp = useAppInitialization();
React.useEffect(() => {
Expand Down Expand Up @@ -72,11 +74,11 @@ export const useAppListeners = () => {
return broadcastService.onBroadcastErrorMessage(setBroadcastError);
}, [setBroadcastError, broadcastService]);

const updateProgress = useReplays((store) => store.updateProgress);
const updateProgress = (progress: Progress | null) => replayPresenter.current.updateProgress(progress);
const throttledUpdateProgress = throttle(updateProgress, 50);
React.useEffect(() => {
return window.electron.replays.onReplayLoadProgressUpdate(throttledUpdateProgress);
}, [throttledUpdateProgress]);
return replayService.onReplayLoadProgressUpdate(throttledUpdateProgress);
}, [throttledUpdateProgress, replayService]);

const updateSettings = useSettings((store) => store.updateSettings);
React.useEffect(() => {
Expand Down Expand Up @@ -131,18 +133,17 @@ export const useAppListeners = () => {
});
}, [isoPath, setIsValid, setIsValidating]);

const clearSelectedFile = useReplays((store) => store.clearSelectedFile);
const { goToReplayStatsPage } = useReplayBrowserNavigation();
const moveToStatsPage = React.useCallback(
(filePath: string) => {
clearSelectedFile();
replayPresenter.current.clearSelectedFile();
goToReplayStatsPage(filePath);
},
[clearSelectedFile, goToReplayStatsPage],
[goToReplayStatsPage],
);
React.useEffect(() => {
return window.electron.replays.onStatsPageRequest(moveToStatsPage);
}, [moveToStatsPage]);
return replayService.onStatsPageRequest(moveToStatsPage);
}, [moveToStatsPage, replayService]);

const { open } = useSettingsModal();
React.useEffect(() => {
Expand All @@ -168,12 +169,11 @@ export const useAppListeners = () => {
}, [setIsReady]);

// Initialize the replay browser once and refresh on SLP path changes
const init = useReplays((store) => store.init);
const rootSlpPath = useSettings((store) => store.settings.rootSlpPath);
const extraSlpPaths = useSettings((store) => store.settings.extraSlpPaths);
React.useEffect(() => {
init(rootSlpPath, extraSlpPaths, true).catch(console.error);
}, [rootSlpPath, JSON.stringify(extraSlpPaths), init]);
replayPresenter.current.init(rootSlpPath, extraSlpPaths, true).catch(console.error);
}, [rootSlpPath, extraSlpPaths]);

const { showError } = useToasts();
React.useEffect(() => {
Expand Down
14 changes: 8 additions & 6 deletions src/renderer/lib/hooks/useReplayBrowserList.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { useRef } from "react";
import { useNavigate } from "react-router-dom";
import create from "zustand";
import { create } from "zustand";
import { combine } from "zustand/middleware";

import { useReplays } from "@/lib/hooks/useReplays";
import { ReplayPresenter, useReplays } from "@/lib/hooks/useReplays";
import { useServices } from "@/services";

import { replayFileFilter, replayFileSort } from "../replayFileSort";
import { useReplayFilter } from "./useReplayFilter";
Expand Down Expand Up @@ -47,9 +49,9 @@ export const useReplayBrowserNavigation = () => {
};

export const useReplayBrowserList = () => {
const { replayService } = useServices();
const presenter = useRef(new ReplayPresenter(replayService));
const files = useReplays((store) => store.files);
const clearSelectedFile = useReplays((store) => store.clearSelectedFile);
const selectFile = useReplays((store) => store.selectFile);
const sortDirection = useReplayFilter((store) => store.sortDirection);
const sortBy = useReplayFilter((store) => store.sortBy);
const searchText = useReplayFilter((store) => store.searchText);
Expand All @@ -63,11 +65,11 @@ export const useReplayBrowserList = () => {

const setSelectedItem = (index: number | null) => {
if (index === null) {
clearSelectedFile();
presenter.current.clearSelectedFile();
return;
}
const file = filteredFiles[index];
selectFile(file, index, filteredFiles.length);
presenter.current.selectFile(file, index, filteredFiles.length);
goToReplayStatsPage(file.fullPath);
};

Expand Down
Loading

0 comments on commit 3a718a2

Please sign in to comment.