Repository: freeCodeCamp/freeCodeCamp
File: client/src/utils/tone/index.ts (TypeScript)

Code before:
  [FlashMessages.SurveyErr2]: TRY_AGAIN,
  [FlashMessages.SurveyErr3]: TRY_AGAIN,
  [FlashMessages.SurveySuccess]: CHAL_COMP,
  [FlashMessages.TimelinePrivate]: TRY_AGAIN,
  [FlashMessages.TokenDeleted]: CHAL_COMP,
  [FlashMessages.UpdatedAboutMe]: CHAL_COMP,
  [FlashMessages.UpdatedKeyboardShortCuts]: CHAL_COMP,
  [FlashMessages.UpdatedPortfolio]: CHAL_COMP,
  [FlashMessages.UpdatedPrivacy]: CHAL_COMP,
  [FlashMessages.UpdatedQunicyEmailSubscription]: CHAL_COMP,
  [FlashMessages.UpdatedSound]: CHAL_COMP,
  [FlashMessages.UpdatedSocials]: CHAL_COMP,
  [FlashMessages.UpdatedThemes]: CHAL_COMP,
  [FlashMessages.UsernameNotFound]: TRY_AGAIN,
  [FlashMessages.UsernameTaken]: TRY_AGAIN,
  [FlashMessages.UsernameUpdated]: CHAL_COMP,
  [FlashMessages.UsernameUsed]: TRY_AGAIN,
  [FlashMessages.UserNotCertified]: TRY_AGAIN,
  [FlashMessages.UserTokenCopied]: CHAL_COMP,
  [FlashMessages.UserTokenCopyError]: TRY_AGAIN,
  [FlashMessages.UserTokenGenerated]: CHAL_COMP,
  [FlashMessages.UserTokenGenerateError]: TRY_AGAIN,
  [FlashMessages.WrongName]: TRY_AGAIN,
  [FlashMessages.WrongUpdating]: TRY_AGAIN,
  [FlashMessages.WentWrong]: TRY_AGAIN,
  [FlashMessages.AccessServerError]: TRY_AGAIN
} as const;

type ToneStates = keyof typeof toneUrls;

export async function playTone(state: ToneStates): Promise<void> {
  const playSound = !!store.get('fcc-sound');
  if (playSound && toneUrls[state]) {
    const Tone = await import('tone');

    const player = new Tone.Player(toneUrls[state]).toDestination();

    const storedVolume = (store.get('soundVolume') as number) ?? 50;
    const calculateDecibel = -60 * (1 - storedVolume / 100);

    player.volume.value = calculateDecibel;

    await Tone.loaded();
    player.start();
  }
}


Review comment (suggestion):
```suggestion
  [FlashMessages.NetworkError]: TRY_AGAIN
```

Code after:
  [FlashMessages.SurveyErr2]: TRY_AGAIN,
  [FlashMessages.SurveyErr3]: TRY_AGAIN,
  [FlashMessages.SurveySuccess]: CHAL_COMP,
  [FlashMessages.TimelinePrivate]: TRY_AGAIN,
  [FlashMessages.TokenDeleted]: CHAL_COMP,
  [FlashMessages.UpdatedAboutMe]: CHAL_COMP,
  [FlashMessages.UpdatedKeyboardShortCuts]: CHAL_COMP,
  [FlashMessages.UpdatedPortfolio]: CHAL_COMP,
  [FlashMessages.UpdatedPrivacy]: CHAL_COMP,
  [FlashMessages.UpdatedQunicyEmailSubscription]: CHAL_COMP,
  [FlashMessages.UpdatedSound]: CHAL_COMP,
  [FlashMessages.UpdatedSocials]: CHAL_COMP,
  [FlashMessages.UpdatedThemes]: CHAL_COMP,
  [FlashMessages.UsernameNotFound]: TRY_AGAIN,
  [FlashMessages.UsernameTaken]: TRY_AGAIN,
  [FlashMessages.UsernameUpdated]: CHAL_COMP,
  [FlashMessages.UsernameUsed]: TRY_AGAIN,
  [FlashMessages.UserNotCertified]: TRY_AGAIN,
  [FlashMessages.UserTokenCopied]: CHAL_COMP,
  [FlashMessages.UserTokenCopyError]: TRY_AGAIN,
  [FlashMessages.UserTokenGenerated]: CHAL_COMP,
  [FlashMessages.UserTokenGenerateError]: TRY_AGAIN,
  [FlashMessages.WrongName]: TRY_AGAIN,
  [FlashMessages.WrongUpdating]: TRY_AGAIN,
  [FlashMessages.WentWrong]: TRY_AGAIN,
  [FlashMessages.UserFetchError]: TRY_AGAIN
} as const;

type ToneStates = keyof typeof toneUrls;

export async function playTone(state: ToneStates): Promise<void> {
  const playSound = !!store.get('fcc-sound');
  if (playSound && toneUrls[state]) {
    const Tone = await import('tone');

    const player = new Tone.Player(toneUrls[state]).toDestination();

    const storedVolume = (store.get('soundVolume') as number) ?? 50;
    const calculateDecibel = -60 * (1 - storedVolume / 100);

    player.volume.value = calculateDecibel;

    await Tone.loaded();
    player.start();
  }
}