From 57e5d81e33a5b26a4d6310790a22fb62a9b8b161 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sun, 24 Apr 2022 14:40:14 -0500 Subject: [PATCH] Convert Redux custom middleware to TypeScript --- app/soapbox/middleware/errors.js | 20 ------------- app/soapbox/middleware/errors.ts | 29 +++++++++++++++++++ .../middleware/{sounds.js => sounds.ts} | 21 ++++++++++---- 3 files changed, 45 insertions(+), 25 deletions(-) delete mode 100644 app/soapbox/middleware/errors.js create mode 100644 app/soapbox/middleware/errors.ts rename app/soapbox/middleware/{sounds.js => sounds.ts} (63%) diff --git a/app/soapbox/middleware/errors.js b/app/soapbox/middleware/errors.js deleted file mode 100644 index b5d9a36a3..000000000 --- a/app/soapbox/middleware/errors.js +++ /dev/null @@ -1,20 +0,0 @@ -import { showAlertForError } from '../actions/alerts'; - -const isFailType = type => type.endsWith('_FAIL'); -const isRememberFailType = type => type.endsWith('_REMEMBER_FAIL'); - -const hasResponse = error => Boolean(error && error.response); - -const shouldShowError = ({ type, skipAlert, error }) => { - return !skipAlert && hasResponse(error) && isFailType(type) && !isRememberFailType(type); -}; - -export default function errorsMiddleware() { - return ({ dispatch }) => next => action => { - if (shouldShowError(action)) { - dispatch(showAlertForError(action.error)); - } - - return next(action); - }; -} diff --git a/app/soapbox/middleware/errors.ts b/app/soapbox/middleware/errors.ts new file mode 100644 index 000000000..b87c50249 --- /dev/null +++ b/app/soapbox/middleware/errors.ts @@ -0,0 +1,29 @@ +import { showAlertForError } from '../actions/alerts'; + +import type { AnyAction } from 'redux'; +import type { ThunkMiddleware } from 'redux-thunk'; + +/** Whether the action is considered a failure. */ +const isFailType = (type: string): boolean => type.endsWith('_FAIL'); + +/** Whether the action is a failure to fetch from browser storage. */ +const isRememberFailType = (type: string): boolean => type.endsWith('_REMEMBER_FAIL'); + +/** Whether the error contains an Axios response. */ +const hasResponse = (error: any): boolean => Boolean(error && error.response); + +/** Whether the error should be shown to the user. */ +const shouldShowError = ({ type, skipAlert, error }: AnyAction): boolean => { + return !skipAlert && hasResponse(error) && isFailType(type) && !isRememberFailType(type); +}; + +/** Middleware to display Redux errors to the user. */ +export default function errorsMiddleware(): ThunkMiddleware { + return ({ dispatch }) => next => action => { + if (shouldShowError(action)) { + dispatch(showAlertForError(action.error)); + } + + return next(action); + }; +} diff --git a/app/soapbox/middleware/sounds.js b/app/soapbox/middleware/sounds.ts similarity index 63% rename from app/soapbox/middleware/sounds.js rename to app/soapbox/middleware/sounds.ts index 6950e7618..94ba15313 100644 --- a/app/soapbox/middleware/sounds.js +++ b/app/soapbox/middleware/sounds.ts @@ -1,6 +1,15 @@ 'use strict'; -const createAudio = sources => { +import type { ThunkMiddleware } from 'redux-thunk'; + +/** Soapbox audio clip. */ +type Sound = { + src: string, + type: string, +} + +/** Produce HTML5 audio from sound data. */ +const createAudio = (sources: Sound[]): HTMLAudioElement => { const audio = new Audio(); sources.forEach(({ type, src }) => { const source = document.createElement('source'); @@ -11,7 +20,8 @@ const createAudio = sources => { return audio; }; -const play = audio => { +/** Play HTML5 sound. */ +const play = (audio: HTMLAudioElement): void => { if (!audio.paused) { audio.pause(); if (typeof audio.fastSeek === 'function') { @@ -24,8 +34,9 @@ const play = audio => { audio.play(); }; -export default function soundsMiddleware() { - const soundCache = { +/** Middleware to play sounds in response to certain Redux actions. */ +export default function soundsMiddleware(): ThunkMiddleware { + const soundCache: Record = { boop: createAudio([ { src: require('../../sounds/boop.ogg'), @@ -49,7 +60,7 @@ export default function soundsMiddleware() { }; return () => next => action => { - if (action.meta && action.meta.sound && soundCache[action.meta.sound]) { + if (action.meta?.sound && soundCache[action.meta.sound]) { play(soundCache[action.meta.sound]); }