Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/zustand #363

Merged
merged 2 commits into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-slider": "^1.1.2",
"@radix-ui/react-toggle-group": "^1.0.4",
"@reduxjs/toolkit": "^1.9.7",
"axios": "^1.5.1",
"chart.js": "^4.4.0",
"csstype": "^3.1.2",
Expand All @@ -39,11 +38,10 @@
"react-i18next": "^13.3.0",
"react-icons": "^4.11.0",
"react-oidc-context": "^2.3.1",
"react-redux": "^8.1.3",
"react-router-dom": "^6.16.0",
"react-waypoint": "^10.3.0",
"redux": "^4.2.1",
"sanitize-html": "^2.11.0"
"sanitize-html": "^2.11.0",
"zustand": "^4.4.3"
},
"devDependencies": {
"@types/react": "^18.2.28",
Expand Down
124 changes: 23 additions & 101 deletions ui/pnpm-lock.yaml

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

42 changes: 22 additions & 20 deletions ui/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ import {createBrowserRouter, createRoutesFromElements, Navigate, Route} from 're
import { useTranslation } from 'react-i18next'
import axios, { AxiosResponse } from 'axios'
import { enqueueSnackbar } from 'notistack'
import { store } from './store/store'
import { useAppDispatch, useAppSelector } from './store/hooks'
import { addPodcast, setNotifications, setSelectedEpisodes } from './store/CommonSlice'
import { setMessages, setProgress } from './store/opmlImportSlice'
import useCommon from './store/CommonSlice'
import useOpmlImport from './store/opmlImportSlice'
import {apiURL, configWSUrl, decodeHTMLEntities, isJsonString} from './utils/Utilities'
import {
UserAdminViewLazyLoad,
Expand Down Expand Up @@ -88,11 +86,15 @@ export const router = createBrowserRouter(createRoutesFromElements(
})

const App: FC<PropsWithChildren> = ({ children }) => {
const dispatch = useAppDispatch()
const config = useAppSelector(state => state.common.configModel)
const podcasts = useAppSelector(state => state.common.podcasts)
const config = useCommon(state => state.configModel)
const podcasts = useCommon(state => state.podcasts)
const addPodcast = useCommon(state => state.addPodcast)
const [socket, setSocket] = useState<WebSocket>()
const { t } = useTranslation()
const setProgress = useOpmlImport(state => state.setProgress)
const setMessages = useOpmlImport(state => state.setMessages)
const setNotifications = useCommon(state => state.setNotifications)
const setSelectedEpisodes = useCommon(state => state.setSelectedEpisodes)

useEffect(() => {
if (socket) {
Expand All @@ -107,24 +109,24 @@ const App: FC<PropsWithChildren> = ({ children }) => {
if (checkIfPodcastAdded(parsed)) {
const podcast = parsed.podcast

dispatch(addPodcast(podcast))
addPodcast(podcast)
enqueueSnackbar(t('new-podcast-added', { name: decodeHTMLEntities(podcast.name) }), { variant: 'success' })
} else if (checkIfPodcastEpisodeAdded(parsed)) {
if (store.getState().common.currentDetailedPodcastId === parsed.podcast_episode.podcast_id) {
if (useCommon.getState().currentDetailedPodcastId === parsed.podcast_episode.podcast_id) {
enqueueSnackbar(t('new-podcast-episode-added', { name: decodeHTMLEntities(parsed.podcast_episode.name) }), { variant: 'success' })

const downloadedPodcastEpisode = parsed.podcast_episode
let res = store.getState().common.selectedEpisodes
let res = useCommon.getState().selectedEpisodes
.find(p => p.podcastEpisode.id === downloadedPodcastEpisode.id)

if (res == undefined) {
// This is a completely new episode
dispatch(setSelectedEpisodes([...store.getState().common.selectedEpisodes, {
setSelectedEpisodes([...useCommon.getState().selectedEpisodes, {
podcastEpisode: downloadedPodcastEpisode
}]))
}])
}

let podcastUpdated:EpisodesWithOptionalTimeline[] = store.getState().common.selectedEpisodes
let podcastUpdated:EpisodesWithOptionalTimeline[] = useCommon.getState().selectedEpisodes
.map(p => {
if (p.podcastEpisode.id === downloadedPodcastEpisode.id) {
const foundDownload = JSON.parse(JSON.stringify(p)) as EpisodesWithOptionalTimeline
Expand All @@ -141,10 +143,10 @@ const App: FC<PropsWithChildren> = ({ children }) => {
return p
})

dispatch(setSelectedEpisodes(podcastUpdated))
setSelectedEpisodes(podcastUpdated)
}
} else if (checkIfPodcastEpisodeDeleted(parsed)) {
const updatedPodcastEpisodes = store.getState().common.selectedEpisodes.map(e => {
const updatedPodcastEpisodes = useCommon.getState().selectedEpisodes.map(e => {
if (e.podcastEpisode.episode_id === parsed.podcast_episode.episode_id) {
const clonedPodcast = Object.assign({}, parsed.podcast_episode)

Expand All @@ -159,18 +161,18 @@ const App: FC<PropsWithChildren> = ({ children }) => {
})

enqueueSnackbar(t('podcast-episode-deleted', { name: decodeHTMLEntities(parsed.podcast_episode.name) }), { variant: 'success' })
dispatch(setSelectedEpisodes(updatedPodcastEpisodes))
setSelectedEpisodes(updatedPodcastEpisodes)
} else if (checkIfPodcastRefreshed(parsed)) {
const podcast = parsed.podcast

enqueueSnackbar(t('podcast-refreshed', { name: decodeHTMLEntities(podcast.name) }), { variant: 'success' })
} else if (checkIfOpmlAdded(parsed)) {
dispatch(setProgress([...store.getState().opmlImport.progress,true]))
setProgress([...useOpmlImport.getState().progress,true])
} else if (checkIfOpmlErrored(parsed)) {
const podcast = parsed

dispatch(setProgress([...store.getState().opmlImport.progress,false]))
dispatch(setMessages([...store.getState().opmlImport.messages, podcast.message]))
setProgress([...useOpmlImport.getState().progress,false])
setMessages([...useOpmlImport.getState().messages, podcast.message])
}
}

Expand All @@ -191,7 +193,7 @@ const App: FC<PropsWithChildren> = ({ children }) => {
const getNotifications = () => {
axios.get(apiURL + '/notifications/unread')
.then((response: AxiosResponse<Notification[]>) => {
dispatch(setNotifications(response.data))
setNotifications(response.data)
})
}

Expand Down
4 changes: 2 additions & 2 deletions ui/src/components/AddPodcastModal.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { FC, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useAppSelector } from '../store/hooks'
import { AddHeader } from './AddHeader'
import { AddTypes } from '../models/AddTypes'
import { FeedURLComponent } from './FeedURLComponent'
import { Modal } from './Modal'
import { OpmlAdd } from './OpmlAdd'
import { ProviderImportComponent } from './ProviderImportComponent'
import useCommon from "../store/CommonSlice";

export const AddPodcastModal: FC = () => {
const {t} = useTranslation()
const [selectedSearchType, setSelectedSearchType] = useState<AddTypes>(AddTypes.ITUNES)
const configModel = useAppSelector(state => state.common.configModel)
const configModel = useCommon(state => state.configModel)

return (
<Modal onCancel={() => {}} onAccept={() => {}} headerText={t('add-podcast')!} onDelete={() => {}} cancelText={"Abbrechen"} acceptText={"Hinzufügen"}>
Expand Down
7 changes: 4 additions & 3 deletions ui/src/components/AudioComponents.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { createRef, useState } from 'react'
import { useAppSelector } from '../store/hooks'
import { AudioAmplifier } from '../models/AudioAmplifier'
import { AudioPlayer } from './AudioPlayer'
import { DetailedAudioPlayer } from './DetailedAudioPlayer'
import useAudioPlayer from "../store/AudioPlayerSlice";
import useCommon from "../store/CommonSlice";

export const AudioComponents = () => {
const ref = createRef<HTMLAudioElement>()
const currentPodcast = useAppSelector(state => state.audioPlayer.currentPodcastEpisode)
const detailedAudioPodcastOpen = useAppSelector(state => state.common.detailedAudioPlayerOpen)
const currentPodcast = useAudioPlayer(state => state.currentPodcastEpisode)
const detailedAudioPodcastOpen = useCommon(state => state.detailedAudioPlayerOpen)
const [audioAmplifier,setAudioAmplifier] = useState<AudioAmplifier>()

return (
Expand Down
6 changes: 3 additions & 3 deletions ui/src/components/AudioPlayer.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { FC, RefObject } from 'react'
import { useAppSelector } from '../store/hooks'
import { AudioAmplifier } from '../models/AudioAmplifier'
import { DrawerAudioPlayer } from './DrawerAudioPlayer'
import { HiddenAudioPlayer } from './HiddenAudioPlayer'
import useCommon from "../store/CommonSlice";

type AudioPlayerProps = {
refItem: RefObject<HTMLAudioElement>,
Expand All @@ -11,8 +11,8 @@ type AudioPlayerProps = {
}

export const AudioPlayer: FC<AudioPlayerProps> = ({ refItem, audioAmplifier, setAudioAmplifier }) => {
const detailedAudioPodcastOpen = useAppSelector(state => state.common.detailedAudioPlayerOpen)
const detailedAudioPodcastOpen = useCommon(state => state.detailedAudioPlayerOpen)

return <>
{!detailedAudioPodcastOpen && <DrawerAudioPlayer refItem={refItem} audioAmplifier={audioAmplifier} />}
<HiddenAudioPlayer refItem={refItem} setAudioAmplifier={setAudioAmplifier} />
Expand Down
Loading