Skip to content

Commit

Permalink
feat: support to show the recent episodes (#24)
Browse files Browse the repository at this point in the history
Co-authored-by: rick <LinuxSuRen@users.noreply.github.com>
  • Loading branch information
LinuxSuRen and LinuxSuRen authored Mar 7, 2024
1 parent 94d11f6 commit a9b590f
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package listening.linuxsuren.github.io.componet;

import listening.linuxsuren.github.io.server.CacheServer;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;

public class CachedImage {
public static ImageIcon ScaledImageIcon(String url) {
return ScaledImageIcon(url, 80, 80);
}

public static ImageIcon ScaledImageIcon(String url, int width, int height) {
try {
BufferedImage image = ImageIO.read(CacheServer.wrapURL(url));

return new ImageIcon(image.getScaledInstance(width, height, Image.SCALE_SMOOTH));
} catch (IOException e) {
e.printStackTrace();
}
return null; // TODO provide a default image
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,13 @@ public void asyncLoad(CollectionService collectionService) {
new Thread(() -> {
collectionService.loadPodcast(podcast);

try {
BufferedImage image = ImageIO.read(CacheServer.wrapURL(podcast.getLogoURL()));
JLabel label = new JLabel();
label.setMinimumSize(new Dimension(80, 80));
label.setIcon(CachedImage.ScaledImageIcon(podcast.getLogoURL()));
label.addMouseListener(mouseListener);
label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));

JLabel label = new JLabel();
label.setMinimumSize(new Dimension(80, 80));
label.setIcon(new ImageIcon(image.getScaledInstance(80, 80, Image.SCALE_SMOOTH)));
label.addMouseListener(mouseListener);
label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));

add(label);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
add(label);

repaint();
revalidate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public class CollectionPanel extends JPanel {
private Podcast podcast;
private JPanel episodeListPanel = new JPanel();
private final JComboBox<Integer> yearBox = new JComboBox<>();
private final JTextField searchField = new JTextField(15);;
private final JTextField searchField = new JTextField(15);
private List<EpisodeEvent> eventList = new ArrayList<>();

public CollectionPanel(CollectionService collectionService) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,7 @@ private JPanel createCenterPanel() {
explorePanel.addEvent((e) -> {
CollectionPanel panel = new CollectionPanel(collectionService);
panel.loadPodcast(e);
panel.addEvent((ee) -> {
EpisodePanel episodePanel = new EpisodePanel(ee);
episodePanel.setPlayEvent(player);
breadCrumbPanel.append(episodePanel);
});
panel.addEvent(showEpisode);

JScrollPane scrollPane = new JScrollPane(panel);
scrollPane.setName(e.getName());
Expand Down Expand Up @@ -163,6 +159,7 @@ private JPopupMenu createPopupMenu() {
JMenuItem reloadMenu = new JMenuItem("Reload");
JMenuItem openConfigMenu = new JMenuItem("Open Config");
JMenuItem addRssMenu = new JMenuItem("Add RSS");
JMenuItem recentEpisodeMenu = new JMenuItem("Recent Episodes");
laterMenu.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
Expand Down Expand Up @@ -192,11 +189,32 @@ public void actionPerformed(ActionEvent e) {
addPodcastDialog.setVisible(true);
}
});
recentEpisodeMenu.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
RecentEpisodePanel recentEpisodePanel = new RecentEpisodePanel();
recentEpisodePanel.reload();
recentEpisodePanel.addEvent(showEpisode);

ScrollPane recentEpisodeScrollPanel = new ScrollPane();
recentEpisodeScrollPanel.add(recentEpisodePanel);
recentEpisodeScrollPanel.setName("Recent");

breadCrumbPanel.append(recentEpisodeScrollPanel);
}
});

popupMenu.add(laterMenu);
popupMenu.add(reloadMenu);
popupMenu.add(openConfigMenu);
popupMenu.add(addRssMenu);
popupMenu.add(recentEpisodeMenu);
return popupMenu;
}

private EpisodeEvent showEpisode = ((Episode episode) -> {
EpisodePanel episodePanel = new EpisodePanel(episode);
episodePanel.setPlayEvent(player);
breadCrumbPanel.append(episodePanel);
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
Copyright 2024 LinuxSuRen.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package listening.linuxsuren.github.io.componet;

import listening.linuxsuren.github.io.service.Episode;
import listening.linuxsuren.github.io.service.SimpleCollectionService;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;

public class RecentEpisodePanel extends JPanel implements ReloadAble {
private final JComboBox<RecentType> recentBox = new JComboBox<>();
private final JPanel centerPanel = new JPanel();
private List<EpisodeEvent> eventList = new ArrayList<>();

public RecentEpisodePanel() {
JPanel toolbar = createToolbar();

// set the center panel
centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.Y_AXIS));

this.setLayout(new BorderLayout());
this.add(toolbar, BorderLayout.NORTH);
this.add(centerPanel, BorderLayout.CENTER);
}

private JPanel createToolbar() {
recentBox.addItem(RecentType.Week);
recentBox.addItem(RecentType.BiWeek);
recentBox.addItem(RecentType.Month);
recentBox.addItemListener((e) -> reload());

JPanel panel = new JPanel();
panel.add(recentBox);
return panel;
}

@Override
public void reload() {
centerPanel.removeAll();

new Thread(() -> {
SimpleCollectionService service = new SimpleCollectionService();

RecentType recentType = (RecentType) recentBox.getSelectedItem();
final ZonedDateTime expectedRange =
ZonedDateTime.now().minusDays(recentType == null ? RecentType.Week.getDays() : recentType.getDays());
service.getAll().forEach(podcast -> {
service.getEpisode(podcast).stream().filter((e) -> e.getPublishDate().isAfter(expectedRange)).
forEach(episode -> {
EpisodeCard card = new EpisodeCard(episode);
card.addTrigger(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
eventList.forEach((episodeEvent -> {
episodeEvent.trigger(episode);
}));
}
});
centerPanel.add(card);
});

revalidate();
});
}).start();
}

public void addEvent(EpisodeEvent e) {
eventList.add(e);
}
}

class EpisodeCard extends JPanel {
private final JLabel logo = new JLabel();

public EpisodeCard(Episode episode) {
JLabel title = new JLabel();
title.setText(episode.getTitle());
BorderUtil.setInsideBorder(title, 10);

logo.setCursor(new Cursor(Cursor.HAND_CURSOR));
logo.setIcon(CachedImage.ScaledImageIcon(episode.getLogoURL()));

this.setLayout(new BorderLayout());
BorderUtil.setInsideBorder(this, 10);
this.add(logo, BorderLayout.WEST);
this.add(title, BorderLayout.CENTER);
}

public void addTrigger(MouseAdapter e) {
logo.addMouseListener(e);
}
}

enum RecentType {
Week, BiWeek, Month;

int getDays() {
switch (this) {
case Week: return 7;
case BiWeek: return 14;
default: return 30;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
Copyright 2024 LinuxSuRen.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package listening.linuxsuren.github.io.componet;

public interface ReloadAble {
void reload();
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class Episode {
private String link;
private ZonedDateTime publishDate;
private Duration duration;
private String logoURL;

public Episode() {}

Expand Down Expand Up @@ -130,6 +131,14 @@ public void setDuration(Duration duration) {
this.duration = duration;
}

public String getLogoURL() {
return logoURL;
}

public void setLogoURL(String logoURL) {
this.logoURL = logoURL;
}

@Override
public int hashCode() {
if (audioURL == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import be.ceau.podcastparser.PodcastParser;
import be.ceau.podcastparser.exceptions.InvalidFeedFormatException;
import be.ceau.podcastparser.models.core.Feed;
import be.ceau.podcastparser.models.support.Image;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
Expand Down Expand Up @@ -148,6 +149,7 @@ public List<Episode> parse(String rssAddress) {
episode.setRssURL(rssAddress);
episode.setDuration(i.getDuration());
episode.setPublishDate(i.getPubDate());
episode.setLogoURL(feed.getImages().stream().findFirst().orElse(new Image()).getUrl());
if (i.getEnclosure() != null) {
episode.setAudioURL(i.getEnclosure().getUrl());
episode.setLength(i.getEnclosure().getLength());
Expand Down

0 comments on commit a9b590f

Please sign in to comment.