diff --git a/ui/src/App.js b/ui/src/App.js
index f8d759b34..ae219623d 100644
--- a/ui/src/App.js
+++ b/ui/src/App.js
@@ -1,5 +1,6 @@
 import React from 'react'
 import ReactGA from 'react-ga'
+import 'react-jinke-music-player/assets/index.css'
 import { Provider } from 'react-redux'
 import { createHashHistory } from 'history'
 import { Admin, Resource } from 'react-admin'
@@ -13,11 +14,14 @@ import song from './song'
 import album from './album'
 import artist from './artist'
 import playlist from './playlist'
-import { Player, playQueueReducer } from './audioplayer'
-import { albumViewReducer } from './album/albumState'
+import { Player } from './audioplayer'
 import customRoutes from './routes'
-import themeReducer from './personal/themeReducer'
-import { addToPlaylistDialogReducer } from './dialogs/dialogState'
+import {
+  themeReducer,
+  addToPlaylistDialogReducer,
+  playQueueReducer,
+  albumViewReducer,
+} from './reducers'
 import createAdminStore from './store/createAdminStore'
 import { i18nProvider } from './i18n'
 import config from './config'
diff --git a/ui/src/actions/albumView.js b/ui/src/actions/albumView.js
new file mode 100644
index 000000000..0439ce717
--- /dev/null
+++ b/ui/src/actions/albumView.js
@@ -0,0 +1,6 @@
+export const ALBUM_MODE_GRID = 'ALBUM_GRID_MODE'
+export const ALBUM_MODE_LIST = 'ALBUM_LIST_MODE'
+
+export const albumViewGrid = () => ({ type: ALBUM_MODE_GRID })
+
+export const albumViewList = () => ({ type: ALBUM_MODE_LIST })
diff --git a/ui/src/actions/audioplayer.js b/ui/src/actions/audioplayer.js
new file mode 100644
index 000000000..7f18738a4
--- /dev/null
+++ b/ui/src/actions/audioplayer.js
@@ -0,0 +1,96 @@
+export const PLAYER_ADD_TRACKS = 'PLAYER_ADD_TRACKS'
+export const PLAYER_PLAY_NEXT = 'PLAYER_PLAY_NEXT'
+export const PLAYER_SET_TRACK = 'PLAYER_SET_TRACK'
+export const PLAYER_SYNC_QUEUE = 'PLAYER_SYNC_QUEUE'
+export const PLAYER_CLEAR_QUEUE = 'PLAYER_CLEAR_QUEUE'
+export const PLAYER_SCROBBLE = 'PLAYER_SCROBBLE'
+export const PLAYER_PLAY_TRACKS = 'PLAYER_PLAY_TRACKS'
+export const PLAYER_CURRENT = 'PLAYER_CURRENT'
+export const PLAYER_SET_VOLUME = 'PLAYER_SET_VOLUME'
+
+export const setTrack = (data) => ({
+  type: PLAYER_SET_TRACK,
+  data,
+})
+
+export const filterSongs = (data, ids) => {
+  if (!ids) {
+    return data
+  }
+  return ids.reduce((acc, id) => ({ ...acc, [id]: data[id] }), {})
+}
+
+export const addTracks = (data, ids) => {
+  const songs = filterSongs(data, ids)
+  return {
+    type: PLAYER_ADD_TRACKS,
+    data: songs,
+  }
+}
+
+export const playNext = (data, ids) => {
+  const songs = filterSongs(data, ids)
+  return {
+    type: PLAYER_PLAY_NEXT,
+    data: songs,
+  }
+}
+
+export const shuffle = (data) => {
+  const ids = Object.keys(data)
+  for (let i = ids.length - 1; i > 0; i--) {
+    let j = Math.floor(Math.random() * (i + 1))
+    ;[ids[i], ids[j]] = [ids[j], ids[i]]
+  }
+  const shuffled = {}
+  // The "_" is to force the object key to be a string, so it keeps the order when adding to object
+  // or else the keys will always be in the same (numerically) order
+  ids.forEach((id) => (shuffled['_' + id] = data[id]))
+  return shuffled
+}
+
+export const shuffleTracks = (data, ids) => {
+  const songs = filterSongs(data, ids)
+  const shuffled = shuffle(songs)
+  const firstId = Object.keys(shuffled)[0]
+  return {
+    type: PLAYER_PLAY_TRACKS,
+    id: firstId,
+    data: shuffled,
+  }
+}
+
+export const playTracks = (data, ids, selectedId) => {
+  const songs = filterSongs(data, ids)
+  return {
+    type: PLAYER_PLAY_TRACKS,
+    id: selectedId || Object.keys(songs)[0],
+    data: songs,
+  }
+}
+
+export const syncQueue = (id, data) => ({
+  type: PLAYER_SYNC_QUEUE,
+  id,
+  data,
+})
+
+export const clearQueue = () => ({
+  type: PLAYER_CLEAR_QUEUE,
+})
+
+export const scrobble = (id, submit) => ({
+  type: PLAYER_SCROBBLE,
+  id,
+  submit,
+})
+
+export const currentPlaying = (audioInfo) => ({
+  type: PLAYER_CURRENT,
+  data: audioInfo,
+})
+
+export const setVolume = (volume) => ({
+  type: PLAYER_SET_VOLUME,
+  data: { volume },
+})
diff --git a/ui/src/actions/dialogs.js b/ui/src/actions/dialogs.js
new file mode 100644
index 000000000..3b5b26d4b
--- /dev/null
+++ b/ui/src/actions/dialogs.js
@@ -0,0 +1,12 @@
+export const ADD_TO_PLAYLIST_OPEN = 'ADD_TO_PLAYLIST_OPEN'
+export const ADD_TO_PLAYLIST_CLOSE = 'ADD_TO_PLAYLIST_CLOSE'
+
+export const openAddToPlaylist = ({ selectedIds, onSuccess }) => ({
+  type: ADD_TO_PLAYLIST_OPEN,
+  selectedIds,
+  onSuccess,
+})
+
+export const closeAddToPlaylist = () => ({
+  type: ADD_TO_PLAYLIST_CLOSE,
+})
diff --git a/ui/src/actions/index.js b/ui/src/actions/index.js
new file mode 100644
index 000000000..23e5c5574
--- /dev/null
+++ b/ui/src/actions/index.js
@@ -0,0 +1,4 @@
+export * from './audioplayer'
+export * from './themes'
+export * from './albumView'
+export * from './dialogs'
diff --git a/ui/src/personal/actions.js b/ui/src/actions/themes.js
similarity index 100%
rename from ui/src/personal/actions.js
rename to ui/src/actions/themes.js
diff --git a/ui/src/album/AlbumActions.js b/ui/src/album/AlbumActions.js
index 62a8f5359..52f482008 100644
--- a/ui/src/album/AlbumActions.js
+++ b/ui/src/album/AlbumActions.js
@@ -11,7 +11,7 @@ import PlayArrowIcon from '@material-ui/icons/PlayArrow'
 import ShuffleIcon from '@material-ui/icons/Shuffle'
 import CloudDownloadOutlinedIcon from '@material-ui/icons/CloudDownloadOutlined'
 import { RiPlayListAddFill, RiPlayList2Fill } from 'react-icons/ri'
-import { playNext, addTracks, playTracks, shuffleTracks } from '../audioplayer'
+import { playNext, addTracks, playTracks, shuffleTracks } from '../actions'
 import subsonic from '../subsonic'
 import { formatBytes } from '../common/SizeField'
 import { useMediaQuery } from '@material-ui/core'
diff --git a/ui/src/album/AlbumList.js b/ui/src/album/AlbumList.js
index f35d9d210..075405fda 100644
--- a/ui/src/album/AlbumList.js
+++ b/ui/src/album/AlbumList.js
@@ -18,7 +18,6 @@ import { List, QuickFilter, Title, useAlbumsPerPage } from '../common'
 import AlbumListActions from './AlbumListActions'
 import AlbumListView from './AlbumListView'
 import AlbumGridView from './AlbumGridView'
-import { ALBUM_MODE_LIST } from './albumState'
 import AddToPlaylistDialog from '../dialogs/AddToPlaylistDialog'
 import albumLists, { defaultAlbumList } from './albumLists'
 
@@ -99,10 +98,10 @@ const AlbumList = (props) => {
         pagination={<Pagination rowsPerPageOptions={perPageOptions} />}
         title={<AlbumListTitle albumListType={albumListType} />}
       >
-        {albumView.mode === ALBUM_MODE_LIST ? (
-          <AlbumListView {...props} />
-        ) : (
+        {albumView.grid ? (
           <AlbumGridView isArtistView={isArtistView} {...props} />
+        ) : (
+          <AlbumListView {...props} />
         )}
       </List>
       <AddToPlaylistDialog />
diff --git a/ui/src/album/AlbumListActions.js b/ui/src/album/AlbumListActions.js
index 00b219d8b..09135bb65 100644
--- a/ui/src/album/AlbumListActions.js
+++ b/ui/src/album/AlbumListActions.js
@@ -4,7 +4,7 @@ import { ButtonGroup } from '@material-ui/core'
 import ViewHeadlineIcon from '@material-ui/icons/ViewHeadline'
 import ViewModuleIcon from '@material-ui/icons/ViewModule'
 import { useDispatch, useSelector } from 'react-redux'
-import { ALBUM_MODE_GRID, ALBUM_MODE_LIST, selectViewMode } from './albumState'
+import { albumViewGrid, albumViewList } from '../actions'
 
 const AlbumListActions = ({
   currentSort,
@@ -44,15 +44,15 @@ const AlbumListActions = ({
       >
         <Button
           size="small"
-          color={albumView.mode === ALBUM_MODE_GRID ? 'primary' : 'secondary'}
-          onClick={() => dispatch(selectViewMode(ALBUM_MODE_GRID))}
+          color={albumView.grid ? 'primary' : 'secondary'}
+          onClick={() => dispatch(albumViewGrid())}
         >
           <ViewModuleIcon fontSize="inherit" />
         </Button>
         <Button
           size="small"
-          color={albumView.mode === ALBUM_MODE_LIST ? 'primary' : 'secondary'}
-          onClick={() => dispatch(selectViewMode(ALBUM_MODE_LIST))}
+          color={albumView.grid ? 'secondary' : 'primary'}
+          onClick={() => dispatch(albumViewList())}
         >
           <ViewHeadlineIcon fontSize="inherit" />
         </Button>
diff --git a/ui/src/album/AlbumSongs.js b/ui/src/album/AlbumSongs.js
index 7b64a4fe1..80426b954 100644
--- a/ui/src/album/AlbumSongs.js
+++ b/ui/src/album/AlbumSongs.js
@@ -11,7 +11,7 @@ import { useDispatch } from 'react-redux'
 import { Card, useMediaQuery } from '@material-ui/core'
 import { makeStyles } from '@material-ui/core/styles'
 import StarBorderIcon from '@material-ui/icons/StarBorder'
-import { playTracks } from '../audioplayer'
+import { playTracks } from '../actions'
 import {
   DurationField,
   SongContextMenu,
diff --git a/ui/src/album/albumState.js b/ui/src/album/albumState.js
deleted file mode 100644
index f5bc84e93..000000000
--- a/ui/src/album/albumState.js
+++ /dev/null
@@ -1,21 +0,0 @@
-const ALBUM_MODE_GRID = 'ALBUM_GRID_MODE'
-const ALBUM_MODE_LIST = 'ALBUM_LIST_MODE'
-const selectViewMode = (mode) => ({ type: mode })
-
-const albumViewReducer = (
-  previousState = {
-    mode: ALBUM_MODE_GRID,
-  },
-  payload
-) => {
-  const { type } = payload
-  switch (type) {
-    case ALBUM_MODE_GRID:
-    case ALBUM_MODE_LIST:
-      return { ...previousState, mode: type }
-    default:
-      return previousState
-  }
-}
-
-export { ALBUM_MODE_LIST, ALBUM_MODE_GRID, albumViewReducer, selectViewMode }
diff --git a/ui/src/audioplayer/Player.js b/ui/src/audioplayer/Player.js
index ca5b784a9..b6d539299 100644
--- a/ui/src/audioplayer/Player.js
+++ b/ui/src/audioplayer/Player.js
@@ -13,7 +13,7 @@ import {
   currentPlaying,
   setVolume,
   clearQueue,
-} from './queue'
+} from '../actions'
 import themes from '../themes'
 import config from '../config'
 import PlayerToolbar from './PlayerToolbar'
diff --git a/ui/src/audioplayer/index.js b/ui/src/audioplayer/index.js
index d14dd0819..5790eb367 100644
--- a/ui/src/audioplayer/index.js
+++ b/ui/src/audioplayer/index.js
@@ -1,21 +1,3 @@
 import Player from './Player'
-import {
-  addTracks,
-  setTrack,
-  playQueueReducer,
-  playTracks,
-  playNext,
-  shuffleTracks,
-  clearQueue,
-} from './queue'
 
-export {
-  Player,
-  addTracks,
-  setTrack,
-  playTracks,
-  playNext,
-  playQueueReducer,
-  shuffleTracks,
-  clearQueue,
-}
+export { Player }
diff --git a/ui/src/common/AddToPlaylistButton.js b/ui/src/common/AddToPlaylistButton.js
index c6b8d6a56..4748a519c 100644
--- a/ui/src/common/AddToPlaylistButton.js
+++ b/ui/src/common/AddToPlaylistButton.js
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
 import { useDispatch } from 'react-redux'
 import { Button, useTranslate, useUnselectAll } from 'react-admin'
 import PlaylistAddIcon from '@material-ui/icons/PlaylistAdd'
-import { openAddToPlaylist } from '../dialogs/dialogState'
+import { openAddToPlaylist } from '../actions'
 
 const AddToPlaylistButton = ({ resource, selectedIds, className }) => {
   const translate = useTranslate()
diff --git a/ui/src/common/ContextMenus.js b/ui/src/common/ContextMenus.js
index 9ee7bdbca..3082ab71b 100644
--- a/ui/src/common/ContextMenus.js
+++ b/ui/src/common/ContextMenus.js
@@ -7,8 +7,13 @@ import MenuItem from '@material-ui/core/MenuItem'
 import MoreVertIcon from '@material-ui/icons/MoreVert'
 import { makeStyles } from '@material-ui/core/styles'
 import { useDataProvider, useNotify, useTranslate } from 'react-admin'
-import { playNext, addTracks, playTracks, shuffleTracks } from '../audioplayer'
-import { openAddToPlaylist } from '../dialogs/dialogState'
+import {
+  playNext,
+  addTracks,
+  playTracks,
+  shuffleTracks,
+  openAddToPlaylist,
+} from '../actions'
 import subsonic from '../subsonic'
 import StarButton from './StarButton'
 import { formatBytes } from './SizeField'
diff --git a/ui/src/common/PlayButton.js b/ui/src/common/PlayButton.js
index b45bc9d94..69698b8e9 100644
--- a/ui/src/common/PlayButton.js
+++ b/ui/src/common/PlayButton.js
@@ -4,7 +4,7 @@ import PlayArrowIcon from '@material-ui/icons/PlayArrow'
 import { IconButton } from '@material-ui/core'
 import { useDispatch } from 'react-redux'
 import { useDataProvider } from 'react-admin'
-import { playTracks } from '../audioplayer'
+import { playTracks } from '../actions'
 import { makeStyles } from '@material-ui/core/styles'
 
 const useStyles = makeStyles({
diff --git a/ui/src/common/ShuffleAllButton.js b/ui/src/common/ShuffleAllButton.js
index 114c0ab88..255a3e5a7 100644
--- a/ui/src/common/ShuffleAllButton.js
+++ b/ui/src/common/ShuffleAllButton.js
@@ -2,7 +2,7 @@ import React from 'react'
 import { Button, useDataProvider, useNotify, useTranslate } from 'react-admin'
 import { useDispatch } from 'react-redux'
 import ShuffleIcon from '@material-ui/icons/Shuffle'
-import { playTracks } from '../audioplayer'
+import { playTracks } from '../actions'
 import PropTypes from 'prop-types'
 
 const ShuffleAllButton = ({ filters }) => {
diff --git a/ui/src/common/SongBulkActions.js b/ui/src/common/SongBulkActions.js
index 3b2efcede..a80eaf2b0 100644
--- a/ui/src/common/SongBulkActions.js
+++ b/ui/src/common/SongBulkActions.js
@@ -1,6 +1,6 @@
 import React, { Fragment, useEffect } from 'react'
 import { useUnselectAll } from 'react-admin'
-import { addTracks, playNext, playTracks } from '../audioplayer'
+import { addTracks, playNext, playTracks } from '../actions'
 import { RiPlayList2Fill, RiPlayListAddFill } from 'react-icons/ri'
 import PlayArrowIcon from '@material-ui/icons/PlayArrow'
 import { BatchPlayButton } from './index'
diff --git a/ui/src/common/SongContextMenu.js b/ui/src/common/SongContextMenu.js
index 5df5f6d86..133ef4e50 100644
--- a/ui/src/common/SongContextMenu.js
+++ b/ui/src/common/SongContextMenu.js
@@ -5,8 +5,7 @@ import { useTranslate } from 'react-admin'
 import { IconButton, Menu, MenuItem } from '@material-ui/core'
 import { makeStyles } from '@material-ui/core/styles'
 import MoreVertIcon from '@material-ui/icons/MoreVert'
-import { playNext, addTracks, setTrack } from '../audioplayer'
-import { openAddToPlaylist } from '../dialogs/dialogState'
+import { playNext, addTracks, setTrack, openAddToPlaylist } from '../actions'
 import subsonic from '../subsonic'
 import StarButton from './StarButton'
 import { formatBytes } from './SizeField'
diff --git a/ui/src/common/SongDatagrid.js b/ui/src/common/SongDatagrid.js
index fce83c799..6431c6fde 100644
--- a/ui/src/common/SongDatagrid.js
+++ b/ui/src/common/SongDatagrid.js
@@ -5,7 +5,7 @@ import { TableCell, TableRow, Typography } from '@material-ui/core'
 import PropTypes from 'prop-types'
 import { makeStyles } from '@material-ui/core/styles'
 import AlbumIcon from '@material-ui/icons/Album'
-import { playTracks } from '../audioplayer'
+import { playTracks } from '../actions'
 import { AlbumContextMenu } from '../common'
 
 const useStyles = makeStyles({
diff --git a/ui/src/dialogs/AddToPlaylistDialog.js b/ui/src/dialogs/AddToPlaylistDialog.js
index 0206196eb..de0d9a44f 100644
--- a/ui/src/dialogs/AddToPlaylistDialog.js
+++ b/ui/src/dialogs/AddToPlaylistDialog.js
@@ -13,7 +13,7 @@ import {
   DialogContent,
   DialogTitle,
 } from '@material-ui/core'
-import { closeAddToPlaylist } from './dialogState'
+import { closeAddToPlaylist } from '../actions'
 import SelectPlaylistInput from './SelectPlaylistInput'
 
 const AddToPlaylistDialog = () => {
diff --git a/ui/src/layout/Login.js b/ui/src/layout/Login.js
index 808cbc850..9ad160600 100644
--- a/ui/src/layout/Login.js
+++ b/ui/src/layout/Login.js
@@ -15,7 +15,7 @@ import { useLogin, useNotify, useTranslate } from 'react-admin'
 import Notification from './Notification'
 import LightTheme from '../themes/light'
 import config from '../config'
-import { clearQueue } from '../audioplayer'
+import { clearQueue } from '../actions'
 
 const useStyles = makeStyles((theme) => ({
   main: {
diff --git a/ui/src/layout/Logout.js b/ui/src/layout/Logout.js
index 9b9a871ae..53a69a02b 100644
--- a/ui/src/layout/Logout.js
+++ b/ui/src/layout/Logout.js
@@ -1,7 +1,7 @@
 import React, { useCallback } from 'react'
 import { useDispatch } from 'react-redux'
 import { Logout } from 'react-admin'
-import { clearQueue } from '../audioplayer'
+import { clearQueue } from '../actions'
 
 export default (props) => {
   const dispatch = useDispatch()
diff --git a/ui/src/personal/Personal.js b/ui/src/personal/Personal.js
index 303c808b3..2095d4688 100644
--- a/ui/src/personal/Personal.js
+++ b/ui/src/personal/Personal.js
@@ -11,7 +11,7 @@ import {
 } from 'react-admin'
 import { makeStyles } from '@material-ui/core/styles'
 import HelpOutlineIcon from '@material-ui/icons/HelpOutline'
-import { changeTheme } from './actions'
+import { changeTheme } from '../actions'
 import themes from '../themes'
 import { docsUrl } from '../utils/docsUrl'
 import { useGetLanguageChoices } from '../i18n'
diff --git a/ui/src/personal/themeReducer.js b/ui/src/personal/themeReducer.js
deleted file mode 100644
index db4c24447..000000000
--- a/ui/src/personal/themeReducer.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import { CHANGE_THEME } from './actions'
-
-export default (previousState = 'DarkTheme', { type, payload }) => {
-  if (type === CHANGE_THEME) {
-    return payload
-  }
-  return previousState
-}
diff --git a/ui/src/playlist/PlaylistActions.js b/ui/src/playlist/PlaylistActions.js
index 0136d05b6..e8dc3d893 100644
--- a/ui/src/playlist/PlaylistActions.js
+++ b/ui/src/playlist/PlaylistActions.js
@@ -12,7 +12,7 @@ import CloudDownloadOutlinedIcon from '@material-ui/icons/CloudDownloadOutlined'
 import { RiPlayListAddFill, RiPlayList2Fill } from 'react-icons/ri'
 import QueueMusicIcon from '@material-ui/icons/QueueMusic'
 import { httpClient } from '../dataProvider'
-import { playNext, addTracks, playTracks, shuffleTracks } from '../audioplayer'
+import { playNext, addTracks, playTracks, shuffleTracks } from '../actions'
 import { M3U_MIME_TYPE, REST_URL } from '../consts'
 import subsonic from '../subsonic'
 import PropTypes from 'prop-types'
diff --git a/ui/src/playlist/PlaylistSongs.js b/ui/src/playlist/PlaylistSongs.js
index 6f4a57ceb..58154515f 100644
--- a/ui/src/playlist/PlaylistSongs.js
+++ b/ui/src/playlist/PlaylistSongs.js
@@ -23,7 +23,7 @@ import {
 } from '../common'
 import AddToPlaylistDialog from '../dialogs/AddToPlaylistDialog'
 import { AlbumLinkField } from '../song/AlbumLinkField'
-import { playTracks } from '../audioplayer'
+import { playTracks } from '../actions'
 
 const useStyles = makeStyles(
   (theme) => ({
diff --git a/ui/src/reducers/albumView.js b/ui/src/reducers/albumView.js
new file mode 100644
index 000000000..b4e00ea79
--- /dev/null
+++ b/ui/src/reducers/albumView.js
@@ -0,0 +1,17 @@
+import { ALBUM_MODE_GRID, ALBUM_MODE_LIST } from '../actions'
+
+export const albumViewReducer = (
+  previousState = {
+    grid: true,
+  },
+  payload
+) => {
+  const { type } = payload
+  switch (type) {
+    case ALBUM_MODE_GRID:
+    case ALBUM_MODE_LIST:
+      return { ...previousState, grid: type === ALBUM_MODE_GRID }
+    default:
+      return previousState
+  }
+}
diff --git a/ui/src/dialogs/dialogState.js b/ui/src/reducers/dialogReducer.js
similarity index 51%
rename from ui/src/dialogs/dialogState.js
rename to ui/src/reducers/dialogReducer.js
index 24702324d..f006d08f6 100644
--- a/ui/src/dialogs/dialogState.js
+++ b/ui/src/reducers/dialogReducer.js
@@ -1,17 +1,6 @@
-const ADD_TO_PLAYLIST_OPEN = 'ADD_TO_PLAYLIST_OPEN'
-const ADD_TO_PLAYLIST_CLOSE = 'ADD_TO_PLAYLIST_CLOSE'
+import { ADD_TO_PLAYLIST_CLOSE, ADD_TO_PLAYLIST_OPEN } from '../actions'
 
-const openAddToPlaylist = ({ selectedIds, onSuccess }) => ({
-  type: ADD_TO_PLAYLIST_OPEN,
-  selectedIds,
-  onSuccess,
-})
-
-const closeAddToPlaylist = () => ({
-  type: ADD_TO_PLAYLIST_CLOSE,
-})
-
-const addToPlaylistDialogReducer = (
+export const addToPlaylistDialogReducer = (
   previousState = {
     open: false,
   },
@@ -32,5 +21,3 @@ const addToPlaylistDialogReducer = (
       return previousState
   }
 }
-
-export { openAddToPlaylist, closeAddToPlaylist, addToPlaylistDialogReducer }
diff --git a/ui/src/reducers/index.js b/ui/src/reducers/index.js
new file mode 100644
index 000000000..28fbb1942
--- /dev/null
+++ b/ui/src/reducers/index.js
@@ -0,0 +1,4 @@
+export * from './themeReducer'
+export * from './dialogReducer'
+export * from './playQueue'
+export * from './albumView'
diff --git a/ui/src/audioplayer/queue.js b/ui/src/reducers/playQueue.js
similarity index 58%
rename from ui/src/audioplayer/queue.js
rename to ui/src/reducers/playQueue.js
index 780554f98..12841fbb2 100644
--- a/ui/src/audioplayer/queue.js
+++ b/ui/src/reducers/playQueue.js
@@ -3,15 +3,17 @@ import get from 'lodash.get'
 import { v4 as uuidv4 } from 'uuid'
 import subsonic from '../subsonic'
 
-const PLAYER_ADD_TRACKS = 'PLAYER_ADD_TRACKS'
-const PLAYER_PLAY_NEXT = 'PLAYER_PLAY_NEXT'
-const PLAYER_SET_TRACK = 'PLAYER_SET_TRACK'
-const PLAYER_SYNC_QUEUE = 'PLAYER_SYNC_QUEUE'
-const PLAYER_CLEAR_QUEUE = 'PLAYER_CLEAR_QUEUE'
-const PLAYER_SCROBBLE = 'PLAYER_SCROBBLE'
-const PLAYER_PLAY_TRACKS = 'PLAYER_PLAY_TRACKS'
-const PLAYER_CURRENT = 'PLAYER_CURRENT'
-const PLAYER_SET_VOLUME = 'PLAYER_SET_VOLUME'
+import {
+  PLAYER_CLEAR_QUEUE,
+  PLAYER_SET_VOLUME,
+  PLAYER_CURRENT,
+  PLAYER_ADD_TRACKS,
+  PLAYER_PLAY_NEXT,
+  PLAYER_SET_TRACK,
+  PLAYER_SYNC_QUEUE,
+  PLAYER_SCROBBLE,
+  PLAYER_PLAY_TRACKS,
+} from '../actions'
 
 const mapToAudioLists = (item) => {
   // If item comes from a playlist, id is mediaFileId
@@ -30,93 +32,6 @@ const mapToAudioLists = (item) => {
   }
 }
 
-const setTrack = (data) => ({
-  type: PLAYER_SET_TRACK,
-  data,
-})
-
-const filterSongs = (data, ids) => {
-  if (!ids) {
-    return data
-  }
-  return ids.reduce((acc, id) => ({ ...acc, [id]: data[id] }), {})
-}
-
-const addTracks = (data, ids) => {
-  const songs = filterSongs(data, ids)
-  return {
-    type: PLAYER_ADD_TRACKS,
-    data: songs,
-  }
-}
-
-const playNext = (data, ids) => {
-  const songs = filterSongs(data, ids)
-  return {
-    type: PLAYER_PLAY_NEXT,
-    data: songs,
-  }
-}
-
-const shuffle = (data) => {
-  const ids = Object.keys(data)
-  for (let i = ids.length - 1; i > 0; i--) {
-    let j = Math.floor(Math.random() * (i + 1))
-    ;[ids[i], ids[j]] = [ids[j], ids[i]]
-  }
-  const shuffled = {}
-  // The "_" is to force the object key to be a string, so it keeps the order when adding to object
-  // or else the keys will always be in the same (numerically) order
-  ids.forEach((id) => (shuffled['_' + id] = data[id]))
-  return shuffled
-}
-
-const shuffleTracks = (data, ids) => {
-  const songs = filterSongs(data, ids)
-  const shuffled = shuffle(songs)
-  const firstId = Object.keys(shuffled)[0]
-  return {
-    type: PLAYER_PLAY_TRACKS,
-    id: firstId,
-    data: shuffled,
-  }
-}
-
-const playTracks = (data, ids, selectedId) => {
-  const songs = filterSongs(data, ids)
-  return {
-    type: PLAYER_PLAY_TRACKS,
-    id: selectedId || Object.keys(songs)[0],
-    data: songs,
-  }
-}
-
-const syncQueue = (id, data) => ({
-  type: PLAYER_SYNC_QUEUE,
-  id,
-  data,
-})
-
-const clearQueue = () => ({
-  type: PLAYER_CLEAR_QUEUE,
-})
-
-const scrobble = (id, submit) => ({
-  type: PLAYER_SCROBBLE,
-  id,
-  submit,
-})
-
-const currentPlaying = (audioInfo) => ({
-  type: PLAYER_CURRENT,
-  data: audioInfo,
-})
-
-const setVolume = (volume) => ({
-  type: PLAYER_SET_VOLUME,
-  data: { volume },
-})
-
 const initialState = {
   queue: [],
   clear: true,
@@ -125,7 +40,7 @@ const initialState = {
   playIndex: 0,
 }
 
-const playQueueReducer = (previousState = initialState, payload) => {
+export const playQueueReducer = (previousState = initialState, payload) => {
   let queue, current
   let newQueue
   const { type, data } = payload
@@ -234,17 +149,3 @@ const playQueueReducer = (previousState = initialState, payload) => {
       return previousState
   }
 }
-
-export {
-  addTracks,
-  setTrack,
-  playTracks,
-  playNext,
-  syncQueue,
-  clearQueue,
-  scrobble,
-  currentPlaying,
-  setVolume,
-  shuffleTracks,
-  playQueueReducer,
-}
diff --git a/ui/src/reducers/themeReducer.js b/ui/src/reducers/themeReducer.js
new file mode 100644
index 000000000..2ca36b993
--- /dev/null
+++ b/ui/src/reducers/themeReducer.js
@@ -0,0 +1,11 @@
+import { CHANGE_THEME } from '../actions'
+
+export const themeReducer = (
+  previousState = 'DarkTheme',
+  { type, payload }
+) => {
+  if (type === CHANGE_THEME) {
+    return payload
+  }
+  return previousState
+}
diff --git a/ui/src/song/SongList.js b/ui/src/song/SongList.js
index 6b832d274..75e124c0b 100644
--- a/ui/src/song/SongList.js
+++ b/ui/src/song/SongList.js
@@ -19,7 +19,7 @@ import {
   SongTitleField,
 } from '../common'
 import { useDispatch } from 'react-redux'
-import { setTrack } from '../audioplayer'
+import { setTrack } from '../actions'
 import { SongBulkActions } from '../common'
 import { SongListActions } from './SongListActions'
 import { AlbumLinkField } from './AlbumLinkField'