Skip to content

Commit

Permalink
count pressed keys
Browse files Browse the repository at this point in the history
  • Loading branch information
yerlantemir committed Aug 5, 2023
1 parent 7711436 commit 9383680
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 40 deletions.
13 changes: 13 additions & 0 deletions frontend/src/app/test/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
'use client';

import { Editor } from '@/components/Editor';
import { Hotkeys } from '@/components/pages/race/Hotkeys/Hotkeys';
import { ExecutedCommand } from '@vimracing/shared';
import { useState } from 'react';

export default function TestPage() {
const [executedCommands, setExecutedCommands] = useState<ExecutedCommand[]>(
[]
);
const [keysCount, setKeysCount] = useState(0);
return (
<div>
<Editor
Expand All @@ -12,6 +19,12 @@ export default function TestPage() {
source: 'kek'
}}
/>
<Hotkeys
executedCommands={executedCommands}
setExecutedCommands={setExecutedCommands}
keysCount={keysCount}
onKeyPressed={() => setKeysCount((prev) => prev + 1)}
/>
</div>
);
}
14 changes: 9 additions & 5 deletions frontend/src/components/pages/race/Hotkeys/Hotkeys.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,29 @@ import { ExecutedCommand } from '@vimracing/shared';
interface IHotkeysProps {
setExecutedCommands?: (ExecutedCommands: ExecutedCommand[]) => void;
executedCommands?: ExecutedCommand[];
keysCount?: number;
onKeyPressed?: (key: string) => void;
}
export const Hotkeys: React.FC<IHotkeysProps> = ({
setExecutedCommands,
executedCommands = []
executedCommands = [],
keysCount,
onKeyPressed
}) => {
const [currentCommand, setCurrentCommand] = useState('');
const [partialCommandExecuted, setPartialCommandExecuted] = useState(false);
const [keysCount, setKeysCount] = useState(0);
const lastPressedKey = useRef('');

useEffect(() => {
const onVimKey = (event: any) => {
lastPressedKey.current = event.detail;
setKeysCount((prev) => prev + 1);
onKeyPressed?.(event.detail);
};
window.addEventListener('vimracing-key', onVimKey);
return () => {
window.removeEventListener('vimracing-key', onVimKey);
};
}, []);
}, [onKeyPressed]);

useEffect(() => {
const onVimCommandDone = (event: any) => {
Expand Down Expand Up @@ -146,7 +149,7 @@ export const Hotkeys: React.FC<IHotkeysProps> = ({
})}
</AnimatePresence>
</div>
<KeysCounter count={keysCount} />
{!!keysCount && <KeysCounter count={keysCount} />}
</>
);
};
Expand All @@ -166,6 +169,7 @@ const KeysCounter: React.FC<{ count: number }> = ({ count }) => {
}, [animate, count, scope]);

if (!count) return null;

return (
<div className="flex justify-center">
<span className="text-xl" ref={scope}>
Expand Down
85 changes: 56 additions & 29 deletions frontend/src/components/pages/race/RaceState.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import { Editor, isTextEqual } from '@/components/Editor';
import { useState, useCallback, useMemo } from 'react';
import { useState, useCallback, useMemo, useEffect } from 'react';
import { Players } from './Players';
import { ExecutedCommand, Player, RaceStatus } from '@vimracing/shared';
import {
RaceDocs,
ExecutedCommand,
Player,
RaceStatus
} from '@vimracing/shared';
import { Hotkeys } from './Hotkeys/Hotkeys';
import { Recap } from './Recap';
import { Timer } from '@/components/Timer';
import { getPostfixedPlace } from '@/utils/postfix';
import { RaceDocs } from '@vimracing/shared';

interface RaceStateProps {
raceDocs: RaceDocs;
onDocChange: (
newDoc: string[],
documentIndex: number,
executedCommands?: ExecutedCommand[]
executedCommands?: ExecutedCommand[],
secondsSinceStart?: number,
keysCount?: number
) => void;
players?: Player[];
currentPlayer?: Player;
Expand All @@ -32,41 +38,60 @@ export const RaceState: React.FC<RaceStateProps> = ({
const [docExecutedCommands, setDocExecutedCommands] = useState<
ExecutedCommand[]
>([]);
const [keysCount, setKeysCount] = useState(0);
const [documentIndex, setDocumentIndex] = useState(
currentPlayer?.raceData?.currentDocIndex ?? 0
);
const [currentDocumentDoc, setCurrentDocumentDoc] = useState(
raceDocs[documentIndex].start
);
const [hasDocumentChange, setHasDocumentChange] = useState(false);

const isDocFinished = (current: string[], target: string[]) => {
return isTextEqual(current, target);
};

const onCurrentDocumentChange = useCallback(
(newDoc: string[]) => {
const isEditingCurrentDoc = !isDocFinished(
newDoc,
raceDocs[documentIndex].target
);
if (isEditingCurrentDoc) {
onDocChange(newDoc, documentIndex);
return;
}
const onCurrentDocumentChange = useCallback((newDoc: string[]) => {
setCurrentDocumentDoc(newDoc);
setHasDocumentChange(true);
}, []);

// current doc finished, move to next doc
const isLastDocument = documentIndex === raceDocs.length - 1;
setDocumentIndex(documentIndex + 1);
setDocExecutedCommands((prev) => {
console.log({ prev, documentIndex });
useEffect(() => {
if (!hasDocumentChange) return;
setHasDocumentChange(false);
const isEditingCurrentDoc = !isDocFinished(
currentDocumentDoc,
raceDocs[documentIndex].target
);

onDocChange(
newDoc,
isLastDocument ? documentIndex : documentIndex + 1,
prev
);
return [];
});
},
[documentIndex, onDocChange, raceDocs]
);
if (isEditingCurrentDoc) {
onDocChange(currentDocumentDoc, documentIndex);
return;
}

// current doc finished, move to next doc
const isLastDocument = documentIndex === raceDocs.length - 1;
setDocumentIndex(documentIndex + 1);
setDocExecutedCommands([]);
setKeysCount(0);

onDocChange(
currentDocumentDoc,
isLastDocument ? documentIndex : documentIndex + 1,
docExecutedCommands,
raceTimer,
keysCount
);
}, [
currentDocumentDoc,
docExecutedCommands,
documentIndex,
hasDocumentChange,
keysCount,
onDocChange,
raceDocs,
raceTimer
]);

const isCurrentPlayerFinished = useMemo(
() =>
Expand Down Expand Up @@ -132,6 +157,8 @@ export const RaceState: React.FC<RaceStateProps> = ({
setExecutedCommands={setDocExecutedCommands}
executedCommands={docExecutedCommands}
key={documentIndex}
keysCount={keysCount}
onKeyPressed={() => setKeysCount(keysCount + 1)}
/>
</>
)}
Expand Down
12 changes: 8 additions & 4 deletions frontend/src/components/pages/race/Recap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ export const Recap: React.FC<IRecapProps> = ({ raceDocs, players }) => {

const finishedPlayers = players.filter(
(player) =>
player.raceData?.executedCommands?.length &&
player.raceData?.executedCommands?.length > 0
player.raceData?.completedDocs?.length &&
player.raceData?.completedDocs?.length > 0
);

return (
Expand All @@ -95,7 +95,10 @@ export const Recap: React.FC<IRecapProps> = ({ raceDocs, players }) => {
)}

{finishedPlayers.map((player) => {
if (!player.raceData?.executedCommands?.[currentRecapTaskIndex])
if (
!player.raceData?.completedDocs?.[currentRecapTaskIndex]
?.executedCommands
)
return null;
return (
<div key={player.id} className="flex items-center gap-4">
Expand All @@ -104,7 +107,8 @@ export const Recap: React.FC<IRecapProps> = ({ raceDocs, players }) => {
</span>
<Hotkeys
executedCommands={
player.raceData?.executedCommands[currentRecapTaskIndex]
player.raceData?.completedDocs?.[currentRecapTaskIndex]
.executedCommands
}
/>
</div>
Expand Down
14 changes: 12 additions & 2 deletions frontend/src/hooks/useRace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,14 +181,24 @@ export const useRace = (raceId: string) => {
(
newDocument: string[],
documentIndex: number,
executedCommands?: ExecutedCommand[]
executedCommands?: ExecutedCommand[],
secondsSinceStart?: number,
keysCount?: number
) => {
const payload: FrontendDocumentChangeEvent = {
event: FrontendEventType.DOCUMENT_CHANGE,
payload: {
docIndex: documentIndex,
newDocument,
executedCommands
...(executedCommands &&
secondsSinceStart &&
keysCount !== undefined && {
sharedDocPayload: {
executedCommands,
seconds: secondsSinceStart,
keysCount
}
})
}
};
socketConnection.current?.send(JSON.stringify(payload));
Expand Down

1 comment on commit 9383680

@vercel
Copy link

@vercel vercel bot commented on 9383680 Aug 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.