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

[ New Feature ] Add Sound Effect #59

Merged
merged 14 commits into from
Jul 5, 2024
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ WORLD_ADDRESS=0x60916a73fe631fcba3b2a930e21c6f7bb2533ea398c7bfa75c72f71a8709fc2
ACCOUNT_CLASS_HASH=0x05400e90f7e0ae78bd02c77cd75527280470e2fe19c54970dd79dc37a9d3645c
FEETOKEN_ADDRESS=0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7
SERVER_PORT=3000
CORE_VERSION=
PUBLIC_MANIFEST_URL=
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"tailwindcss": "^3.4.4",
"tailwindcss-animate": "^1.0.7",
"upng-js": "^2.1.0",
"use-sound": "^4.0.3",
"zustand": "^4.5.4"
},
"devDependencies": {
Expand Down
18 changes: 18 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added public/assets/sounds/effects/error.mp3
Binary file not shown.
Binary file added public/assets/sounds/effects/place_color.mp3
Binary file not shown.
Binary file added public/assets/sounds/effects/success.mp3
Binary file not shown.
2 changes: 1 addition & 1 deletion src/App.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ body {
background: rgba(31, 41, 55, 0.95);
border-radius: 8px;
overflow-y: hidden;
z-index: 1000;
z-index: 998;
padding: 16px;
padding-bottom: 0%;
}
Expand Down
12 changes: 8 additions & 4 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
import FilterMenu from './components/FilterMenu/FilterMenu';
import SimpleColorPicker from '@/components/ColorPicker/SimpleColorPicker.tsx';
import MenuBar from '@/components/MenuBar/MenuBar.tsx';
import { GAME_ID } from '@/global/constants.ts';
import { GAME_ID, sounds } from '@/global/constants.ts';
import useBoard from '@/hooks/useBoard.ts';
import { useSound } from 'use-sound';
import { useDojoPixelStore } from '@/stores/DojoPixelStore.ts';
import Viewport from '@/webtools/components/Viewport/ViewPort.tsx';
import { useSimpleTileStore } from '@/webtools/hooks/SimpleTileStore.ts';
Expand Down Expand Up @@ -50,6 +51,7 @@
setClickedCell,
setSelectedApp, // added
} = useViewStateStore();
const [play] = useSound(sounds.placeColor);

// FIXME: should be in the ViewStateStore??
const [isColorPickerVisible, setIsColorPickerVisible] = useState(false);
Expand Down Expand Up @@ -82,7 +84,7 @@
console.log('updateService.tileChanged', updateService.tileChanged);
tileStore.fetchTile(updateService.tileChanged!.tileName);
pixelStore.refresh();
}, [updateService.tileChanged]);

Check warning on line 87 in src/App.tsx

View workflow job for this annotation

GitHub Actions / lint-n-format (20.x)

React Hook useEffect has missing dependencies: 'pixelStore' and 'tileStore'. Either include them or remove the dependency array

const board = useBoard(GAME_ID);

Expand Down Expand Up @@ -121,7 +123,7 @@
});
}
}
}, [hasBoard]);

Check warning on line 126 in src/App.tsx

View workflow job for this annotation

GitHub Actions / lint-n-format (20.x)

React Hook useEffect has missing dependencies: 'board.data' and 'pixelStore'. Either include them or remove the dependency array
function onWorldviewChange(newWorldview: Bounds) {
updateService.setBounds(newWorldview);
pixelStore.prepare(newWorldview);
Expand All @@ -138,6 +140,7 @@
if (!isCoordinateInBounds(coordinate, bounds)) return;
}
setClickedCell(coordinate);
play();
}

function onColorSelect(color: string) {
Expand Down Expand Up @@ -179,7 +182,7 @@
// return '1rem';
// }
// return '-100%';
}, [zoom]);

Check warning on line 185 in src/App.tsx

View workflow job for this annotation

GitHub Actions / lint-n-format (20.x)

React Hook useMemo has an unnecessary dependency: 'zoom'. Either exclude it or remove the dependency array

//</editor-fold>

Expand Down Expand Up @@ -276,10 +279,12 @@
)}
</div>
<button
className={`ml-auto text-white ${isProposalListVisible ? 'rotate-180' : ''} transition duration-300`}
className='ml-auto bg-gray-700 transition duration-300'
onClick={toggleProposalList}
>
<FaArrowDown />
<FaArrowDown
className={`text-white ${isProposalListVisible ? 'rotate-180' : ''}`}
/>
</button>
</div>
{isProposalListVisible && (
Expand Down Expand Up @@ -320,7 +325,6 @@
<ToastContainer
position='top-right'
className={'top-12 z-999 w-full min-w-[200px] max-w-[420px]'}
limit={2}
transition={Slide}
closeButton={false}
newestOnTop
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import Select, {
type SingleValue,
} from 'react-select';
import { ProposalType } from '@/global/types';
import { GAME_ID } from '@/global/constants';
import { GAME_ID, sounds } from '@/global/constants';
import { usePixelawProvider } from '@/providers/PixelawProvider';
import { hexRGBtoNumber, numRGBAToHex, toastContractError } from '@/global/utils.ts';
import useAllowedColors from '@/hooks/useAllowedColors.ts';
import { useSound } from 'use-sound';

const NewProposalPopupForMain: React.FC = () => {
const [proposalType, setProposalType] = useState<ProposalType>(ProposalType.AddNewColor);
Expand All @@ -20,6 +21,8 @@ const NewProposalPopupForMain: React.FC = () => {
const colorPickerRef = useRef<HTMLDivElement | null>(null);
const popupRef = useRef<HTMLDivElement | null>(null);

const [playError] = useSound(sounds.error, { volume: 0.5 });

const { gameData } = usePixelawProvider();

const handleColorChange = (color: string) => {
Expand Down Expand Up @@ -72,6 +75,7 @@ const NewProposalPopupForMain: React.FC = () => {
.catch((e) => {
console.error('handleSubmit error: ', e);
toastContractError(e);
playError();
});
}
};
Expand Down
15 changes: 13 additions & 2 deletions src/components/NewProposalPopupForMain/ProposalListForMain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
import React, { useState, useRef, useEffect } from 'react';
import ProposalItem, { type StartVoteParam } from '../ProposalList/ProposalItem';
import { usePixelawProvider } from '@/providers/PixelawProvider';
import { GAME_ID } from '@/global/constants.ts';
import { GAME_ID, sounds } from '@/global/constants.ts';
import { toastContractError } from '@/global/utils.ts';
import useProposals from '@/hooks/useProposals.ts';
import { toastSuccess } from '../Toast';
import { useSound } from 'use-sound';

interface ProposalListForMainProps {
headerHeight: number;
Expand All @@ -19,6 +21,8 @@ const ProposalListForMain: React.FC<ProposalListForMainProps> = ({
const [searchTerm, setSearchTerm] = useState('');
const filterRef = useRef<HTMLDivElement>(null);
const modalRef = useRef<HTMLDivElement>(null);
const [playSuccess] = useSound(sounds.success, { volume: 0.5 });
const [playError] = useSound(sounds.error, { volume: 0.5 });

const [selectedProposal, setSelectedProposal] = useState<StartVoteParam | null>(null);
const [voteType, setVoteType] = useState<'for' | 'against'>('for');
Expand Down Expand Up @@ -84,10 +88,17 @@ const ProposalListForMain: React.FC<ProposalListForMainProps> = ({
votePoints === '' ? 0 : votePoints,
voteType === 'for',
)
.then(() => setSelectedProposal(null))
.then(() => {
setSelectedProposal(null);
toastSuccess({
message: `Vote submitted`,
});
playSuccess();
})
.catch((e) => {
console.error('handleVoteProposal error: ', e);
toastContractError(e);
playError();
});
};

Expand Down
11 changes: 4 additions & 7 deletions src/components/ProposalList/ProposalItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@
switch (proposalType) {
case ProposalType.AddNewColor:
return `Adding A New Color: ${hexColor.toUpperCase()}`;
case ProposalType.ResetToWhiteByColor:
return `Reset To White: ${hexColor.toUpperCase()}`;
case ProposalType.MakeADisasterByColor:
return `Make A Disaster: ${hexColor.toUpperCase()}`;
case ProposalType.ResetToWhiteByColor:
return `Reset To White: ${hexColor.toUpperCase()}`;
default: {
console.error('unhandled proposal type: ', proposalType);
return '';
Expand Down Expand Up @@ -136,7 +136,7 @@
if (!gameData?.account.account) return;
gameData.setup.systemCalls
.activateProposal(gameData.account.account, GAME_ID, proposal.index)
.then(() => console.log('activateProposal'))
.then(() => console.log('activateProposal', proposal))
.catch((e) => {
console.error('handleActivateProposal error: ', e);
toastContractError(e);
Expand All @@ -151,10 +151,7 @@
proposal.is_activated;

return (
<div
// className='relative bg-gray-800 p-4 rounded-md border border-gray-700 hover:border-gray-600 transition-colors duration-300'>
className={containerClassName}
>
<div className={containerClassName}>
<div className='block'>
<div className='mb-1 flex items-center justify-between'>
<div
Expand All @@ -179,7 +176,7 @@
proposed by {formatWalletAddress(proposal.author.toString())}
</div>
<div
className='mr-30 relative mb-1 flex h-2 rounded-full bg-gray-700'

Check warning on line 179 in src/components/ProposalList/ProposalItem.tsx

View workflow job for this annotation

GitHub Actions / lint-n-format (20.x)

Classname 'mr-30' is not a Tailwind CSS class!
style={{ marginRight: '7rem' }}
>
<div
Expand All @@ -196,7 +193,7 @@
/>
</div>
<div
className='mr-30 flex justify-between text-xs text-gray-300'

Check warning on line 196 in src/components/ProposalList/ProposalItem.tsx

View workflow job for this annotation

GitHub Actions / lint-n-format (20.x)

Classname 'mr-30' is not a Tailwind CSS class!
style={{ marginRight: '7rem' }}
>
<div>For {proposal.yes_px} points</div>
Expand Down
53 changes: 35 additions & 18 deletions src/components/Toast/index.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,50 @@
import {Slide, toast, ToastContainer} from 'react-toastify'
import 'react-toastify/dist/ReactToastify.css'
import { Slide, toast, ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';

type ToastType = {
message: string
}
message: string;
};

export const toastSuccess = ({message}: ToastType) =>
export const toastSuccess = ({ message }: ToastType) =>

Check warning on line 8 in src/components/Toast/index.tsx

View workflow job for this annotation

GitHub Actions / lint-n-format (20.x)

Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components
toast.success(message, {
icon: (
<img src="/assets/svg/icon_toast_success.svg" alt={'Success Toast'} width={'43px'} height={'43px'}/>
<img
src='/assets/svg/icon_toast_success.svg'
alt={'Success Toast'}
width={'43px'}
height={'43px'}
/>
),
})
export const toastError = ({message}: ToastType) =>
});
export const toastError = ({ message }: ToastType) =>

Check warning on line 19 in src/components/Toast/index.tsx

View workflow job for this annotation

GitHub Actions / lint-n-format (20.x)

Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components
toast.error(message, {
icon: <img src="/assets/svg/icon_toast_error.svg" alt={'Error Toast'} width={'43px'} height={'43px'}/>,
})
export const toastWarn = ({message}: ToastType) =>
icon: (
<img
src='/assets/svg/icon_toast_error.svg'
alt={'Error Toast'}
width={'43px'}
height={'43px'}
/>
),
});
export const toastWarn = ({ message }: ToastType) =>
toast.warn(message, {
icon: (
<img src="/assets/svg/icon_toast_warning.svg" alt={'Warning Toast'} width={'43px'} height={'43px'}/>
<img
src='/assets/svg/icon_toast_warning.svg'
alt={'Warning Toast'}
width={'43px'}
height={'43px'}
/>
),
})
});

const Toast = () => {
return (
<>
<ToastContainer
position="top-right"
className={'z-999 top-auto w-full min-w-[200px] max-w-[420px]'}
position='top-right'
className={'top-auto z-999 w-full min-w-[200px] max-w-[420px]'}
limit={2}
transition={Slide}
closeButton={false}
Expand All @@ -43,7 +60,7 @@
}}
/>
</>
)
}
);
};

export default Toast
export default Toast;
6 changes: 6 additions & 0 deletions src/global/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,9 @@ export const proposals = [
comments: '',
},
];

export const sounds = {
placeColor: '/assets/sounds/effects/place_color.mp3',
success: '/assets/sounds/effects/success.mp3',
error: '/assets/sounds/effects/error.mp3',
};
4 changes: 4 additions & 0 deletions src/hooks/useDojoInteractHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@
import { coordinateToPosition, hexRGBtoNumber, toastContractError } from '@/global/utils.ts';
import { useViewStateStore } from '@/stores/ViewStateStore.ts';
import { type PixelStore } from '@/webtools/types.ts';
import { useSound } from 'use-sound';
import { sounds } from '@/global/constants';

// TODO maybe cleaner to directly use the Dojo hook here, but its not working.
// For now passing the pixelStore
export const useDojoInteractHandler = (pixelStore: PixelStore, gameData: IPixelawGameData) => {
const { setClickedCell, clickedCell, selectedApp, color } = useViewStateStore();
const [playError] = useSound(sounds.error, { volume: 0.5 });

useEffect(() => {
if (!clickedCell || !selectedApp) return;
Expand Down Expand Up @@ -64,7 +67,8 @@
.catch((e) => {
console.error('dojocall error', e);
toastContractError(e);
playError();
});
setClickedCell(undefined);
}, [setClickedCell, clickedCell, color, selectedApp, pixelStore, gameData]);

Check warning on line 73 in src/hooks/useDojoInteractHandler.ts

View workflow job for this annotation

GitHub Actions / lint-n-format (20.x)

React Hook useEffect has a missing dependency: 'playError'. Either include it or remove the dependency array
};
7 changes: 6 additions & 1 deletion src/hooks/useProposals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import GetProposals from '@/../graphql/GetProposals.graphql';
import { toastSuccess } from '@/components/Toast';
import { usePixelawProvider } from '@/providers/PixelawProvider.tsx';
import { useSettingsStore } from '@/stores/SettingsStore.ts';
import { sounds } from '@/global/constants';
import { useSound } from 'use-sound';

export type ProposalDataType = {
game_id: number;
Expand Down Expand Up @@ -80,6 +82,7 @@ type SubscriptionMessageType = {
};

export const useProposalSubscription = () => {
const [play] = useSound(sounds.success, { volume: 0.5 });
const settings = useSettingsStore();
const baseUrl = settings?.config?.toriiUrl ?? 'http://localhost:8080';
const client = createClient({
Expand Down Expand Up @@ -118,6 +121,8 @@ export const useProposalSubscription = () => {
toastSuccess({
message: `${playerAddress} just created a new proposal`,
});

play();
});
},
error: (err) => console.error(err),
Expand All @@ -126,5 +131,5 @@ export const useProposalSubscription = () => {
);

return () => unsubscribe();
}, [gameData, queryClient, client]);
}, [gameData, queryClient, client, play]);
};
2 changes: 2 additions & 0 deletions src/vite-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
ACCOUNT_CLASS_HASH: string
FEETOKEN_ADDRESS: string
SERVER_PORT: string
CORE_VERSION: string
PUBLIC_MANIFEST_URL: string
// @user-defined-start
/*
* Here you can define your own special variables
Expand All @@ -34,9 +36,9 @@

url: string

readonly hot?: import('vite-envs/types/hot').ViteHotContext

Check warning on line 39 in src/vite-env.d.ts

View workflow job for this annotation

GitHub Actions / lint-n-format (20.x)

`import()` type annotations are forbidden

readonly env: ImportMetaEnv

glob: import('vite-envs/types/importGlob').ImportGlobFunction

Check warning on line 43 in src/vite-env.d.ts

View workflow job for this annotation

GitHub Actions / lint-n-format (20.x)

`import()` type annotations are forbidden
}
Loading