Overview
The episode management system allows you to organize and track your podcast listening experience. All episode states are persisted to localStorage, ensuring your preferences are saved across sessions.
Episode States
Each episode can be in one or more of the following states:
- Started - Episodes you’ve begun listening to
- Not Started - Episodes you haven’t played yet
- Completed - Episodes you’ve finished listening to
- Favorites - Episodes you’ve marked as favorites
- Listen Later - Episodes saved for future listening
Managing Favorites
Adding to Favorites
Click the heart icon on any episode card or detail page to mark it as a favorite.
Find the Episode
Navigate to any episode card or detail page
Click Heart Icon
Click the heart outline icon (hollow heart)
Confirm
The heart fills in to confirm the episode is favorited
Implementation
The favorite toggle functionality is handled by Redux:
toggleFavorite: (state, action) => {
const songTitle = action.payload.title;
const isFavorite = state.favoriteEpisodes.includes(songTitle);
if (isFavorite) {
state.favoriteEpisodes = state.favoriteEpisodes.filter(
(title) => title !== songTitle
);
} else {
state.favoriteEpisodes.push(songTitle);
}
localStorage.setItem("nsnPodcastFavorites", JSON.stringify(state.favoriteEpisodes));
}
Favorites are stored in localStorage under the key nsnPodcastFavorites as a JSON array of episode titles.
Viewing Favorites
Filter to show only favorite episodes by clicking the heart icon in the filter bar on the main page.
Listen Later
Saving Episodes for Later
The Listen Later feature allows you to queue episodes you want to hear soon.
toggleListenLater: (state, action) => {
const songTitle = action.payload.title;
const isListenLater = state.listenLaterEpisodes.includes(songTitle);
if (isListenLater) {
state.listenLaterEpisodes = state.listenLaterEpisodes.filter(
(title) => title !== songTitle
);
} else {
state.listenLaterEpisodes.push(songTitle);
}
localStorage.setItem(
"nsnPodcastListenLater",
JSON.stringify(state.listenLaterEpisodes)
);
}
Using Listen Later
Mark Episode
Click the clock icon on an episode card
Access Queue
Click the clock filter button to view all saved episodes
Start Listening
Play episodes from your Listen Later queue
Auto-Remove
Episodes can be manually removed by clicking the icon again
Use Listen Later to build a personalized queue of episodes you plan to hear soon, separate from your favorites.
Completion Tracking
Automatic Completion
Episodes are automatically marked as completed when:
- Playback reaches the end of the episode
- The
handleEnded event fires
const handleEnded = () => {
dispatch(updatePlaybackTime({ title: currentPodcast.title, time: 0 }));
dispatch(markAsCompleted(currentPodcast.title));
};
Manual Completion
You can also manually mark episodes as completed:
const handleCompleteClick = () => {
if (isCompleted) {
dispatch(removeFromCompleted(podcast.title));
} else {
dispatch(markAsCompleted(podcast.title));
}
};
You cannot manually mark an episode as completed while it’s currently playing. The button will be disabled during playback.
Completion State Management
markAsCompleted: (state, action) => {
const songTitle = action.payload;
if (!state.completedEpisodes.includes(songTitle)) {
state.completedEpisodes.push(songTitle);
localStorage.setItem(
"nsnPodcastCompleted",
JSON.stringify(state.completedEpisodes)
);
}
},
removeFromCompleted: (state, action) => {
const songTitle = action.payload;
state.completedEpisodes = state.completedEpisodes.filter(
(title) => title !== songTitle
);
localStorage.setItem("nsnPodcastCompleted", JSON.stringify(state.completedEpisodes));
}
Progress Tracking
Started Episodes
Episodes automatically enter the “Started” state when:
- You begin playback for the first time
- Playback time is saved and greater than 0 seconds
const isStarted = playbackTimes[song.title] > 0;
const isCompleted = completedEpisodes.includes(song.title);
Visual Indicators
Episode cards display status with icons:
Headphones Icon - Shows for started episodes with playback time:
{isStarted && !isCompleted && (
<div className={styles.favoriteContainer}>
<BootstrapTooltip
title={
<Typography style={{ fontSize: "14px", fontWeight: "bold", textAlign: "center" }}>
{`Empezado - ${formatTime(playbackTime)}`}
<br />
{!isPlaying && "Clic para eliminar el tiempo"}
</Typography>
}
placement="top"
arrow
>
<Headphones
style={{ color: "#17D891", position: "absolute", top: "78px", right: "0px" }}
onClick={(e) => handleRemoveStarted(title, e)}
/>
</BootstrapTooltip>
</div>
)}
Hover over the headphones icon to see the exact playback time where you left off.
Removing Progress
Clearing Playback Time
You can remove saved playback time to start an episode fresh:
const handleRemoveStarted = (title, e) => {
e.stopPropagation();
if (!isPlaying) {
showConfirmToast(
"¿Estás seguro de que quieres eliminar el tiempo de reproducción guardado?",
() => {
dispatch(deleteEpisode(title));
dispatch(removePlaybackTime(title));
toast.success("Tiempo de reproducción eliminado", {
position: isMobile ? "bottom-center" : "bottom-left",
style: {
backgroundColor: "rgba(33, 33, 33, 0.9)",
color: "#ffffff",
borderRadius: "8px",
padding: "10px",
boxShadow: "0px 4px 15px rgba(0, 0, 0, 0.2)"
}
});
}
);
}
};
You cannot remove playback time while an episode is currently playing. The action is blocked to prevent data inconsistency.
Bulk Operations
The Settings page provides bulk operations for episode management:
Clear All Favorites
clearFavorites: (state) => {
state.favoriteEpisodes = [];
localStorage.setItem("nsnPodcastFavorites", JSON.stringify([]));
}
Clear Listen Later Queue
clearListenLater: (state) => {
state.listenLaterEpisodes = [];
localStorage.setItem("nsnPodcastListenLater", JSON.stringify([]));
}
Clear Started Episodes
clearStarted: (state) => {
state.listenedEpisodes = [];
localStorage.setItem("nsnPodcastListened", JSON.stringify([]));
}
Clear Completed Episodes
clearCompleted: (state) => {
state.completedEpisodes = [];
localStorage.setItem("nsnPodcastCompleted", JSON.stringify([]));
}
Bulk clear operations cannot be undone. A confirmation dialog appears before executing these actions.
LocalStorage Keys
The application uses the following localStorage keys:
| Key | Purpose | Format |
|---|
nsnPodcastFavorites | Favorite episodes | JSON array of titles |
nsnPodcastListenLater | Listen later queue | JSON array of titles |
nsnPodcastCompleted | Completed episodes | JSON array of titles |
nsnPodcastListened | Listened episodes | JSON array of titles |
nsnPlayerVolume | Volume setting | Float (0-1) |
nsnPlaybackTimes | Playback positions | JSON object (title: seconds) |
All episode management features work offline and sync automatically across browser tabs on the same device.
Best Practices
Mark Favorites
Star episodes you loved to easily find them later
Use Listen Later
Queue up episodes when you discover them but aren’t ready to listen
Track Completion
Let episodes auto-complete or manually mark them to keep your library organized
Regular Cleanup
Periodically review and clear old entries from your lists