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

feat: support to show the recent episodes #24

Merged
merged 1 commit into from
Mar 7, 2024
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
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) {

Check notice on line 12 in src/main/java/listening/linuxsuren/github/io/componet/CachedImage.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/main/java/listening/linuxsuren/github/io/componet/CachedImage.java#L12

The static method name 'ScaledImageIcon' doesn't match '[a-z][a-zA-Z0-9]*'
return ScaledImageIcon(url, 80, 80);
}

public static ImageIcon ScaledImageIcon(String url, int width, int height) {

Check notice on line 16 in src/main/java/listening/linuxsuren/github/io/componet/CachedImage.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/main/java/listening/linuxsuren/github/io/componet/CachedImage.java#L16

The static method name 'ScaledImageIcon' doesn't match '[a-z][a-zA-Z0-9]*'
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 @@
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 @@
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 @@
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) -> {

Check notice on line 215 in src/main/java/listening/linuxsuren/github/io/componet/MainPanel.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/main/java/listening/linuxsuren/github/io/componet/MainPanel.java#L215

Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes.
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
Loading