From 0a1d96d4f9008fc56af5e65f90f6fed774971e31 Mon Sep 17 00:00:00 2001 From: Christian F Date: Thu, 27 Jul 2023 10:28:15 +0200 Subject: [PATCH 001/184] - fixes #696 - fix incorrect description of download play action - switch to nightly - catch some exceptions in download list when removing or selecting entries --- CHANGELOG.md | 3 + .../java/mediathek/config/Konstanten.java | 4 +- .../gui/actions/PlayDownloadAction.java | 5 +- .../gui/tabs/tab_downloads/GuiDownloads.java | 78 ++++++++++--------- 4 files changed, 48 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a15f96b49a..7cdb8a2b1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# **14.0.1** +- **BUGFIX:** Inkorrekte Beschreibung des "Gespeicherten Film abspielen" Toolbar-Button im Tab Download wurde korrigiert. + # **14.0.0** - Es wird nun Java 20 verwendet. - User Interface wurde primär für neue macOS-Versionen überarbeitet. diff --git a/src/main/java/mediathek/config/Konstanten.java b/src/main/java/mediathek/config/Konstanten.java index 906f0a64f4..93557a88fe 100644 --- a/src/main/java/mediathek/config/Konstanten.java +++ b/src/main/java/mediathek/config/Konstanten.java @@ -27,9 +27,9 @@ public class Konstanten { public static final long MINIMUM_MEMORY_THRESHOLD = 768 * FileUtils.ONE_MB; - public static final Version MVVERSION = new Version(14,0,0); + public static final Version MVVERSION = new Version(14,0,1); - public static final ApplicationType APPLICATION_TYPE = ApplicationType.PRODUCTION; + public static final ApplicationType APPLICATION_TYPE = ApplicationType.NIGHTLY; public static final String MACOS_OFFICIAL_APP = "OSX_OFFICIAL_APP"; public static final String FORMAT_ZIP = ".zip"; diff --git a/src/main/java/mediathek/gui/actions/PlayDownloadAction.java b/src/main/java/mediathek/gui/actions/PlayDownloadAction.java index e260aab89c..2df6c56689 100644 --- a/src/main/java/mediathek/gui/actions/PlayDownloadAction.java +++ b/src/main/java/mediathek/gui/actions/PlayDownloadAction.java @@ -7,12 +7,13 @@ import java.awt.event.ActionEvent; public class PlayDownloadAction extends AbstractAction { + private static final String ACTION_TEXT = "Gespeicherten Film abspielen"; private final GuiDownloads guiDownloads; public PlayDownloadAction(GuiDownloads guiDownloads) { this.guiDownloads = guiDownloads; - putValue(Action.NAME, "Gespeicherten Film abspielen"); - putValue(Action.SHORT_DESCRIPTION, "Film abspielen"); + putValue(Action.NAME, ACTION_TEXT); + putValue(Action.SHORT_DESCRIPTION, ACTION_TEXT); putValue(Action.SMALL_ICON, SVGIconUtilities.createSVGIcon("icons/fontawesome/play.svg")); } diff --git a/src/main/java/mediathek/gui/tabs/tab_downloads/GuiDownloads.java b/src/main/java/mediathek/gui/tabs/tab_downloads/GuiDownloads.java index 4d9dd996b6..331bd982fb 100644 --- a/src/main/java/mediathek/gui/tabs/tab_downloads/GuiDownloads.java +++ b/src/main/java/mediathek/gui/tabs/tab_downloads/GuiDownloads.java @@ -202,21 +202,25 @@ private void updateFilmSizes(int[] rows) { boolean updateNeeded = false; for (var row : rows) { - var indexRow = tabelle.convertRowIndexToModel(row); - var listeDownloads = daten.getListeDownloads(); - var dlInfo = listeDownloads.get(indexRow); - if (dlInfo != null) { - if (dlInfo.mVFilmSize.getSize() != 0) - continue; + try { + var indexRow = tabelle.convertRowIndexToModel(row); + var listeDownloads = daten.getListeDownloads(); + var dlInfo = listeDownloads.get(indexRow); + if (dlInfo != null) { + if (dlInfo.mVFilmSize.getSize() != 0) + continue; - if (dlInfo.film != null) { - var oldSize = dlInfo.mVFilmSize.getSize(); - dlInfo.queryLiveSize(); - if (dlInfo.mVFilmSize.getSize() != oldSize) - updateNeeded = true; - } - } else - logger.error("Could not get download object"); + if (dlInfo.film != null) { + var oldSize = dlInfo.mVFilmSize.getSize(); + dlInfo.queryLiveSize(); + if (dlInfo.mVFilmSize.getSize() != oldSize) + updateNeeded = true; + } + } else + logger.error("Could not get download object"); + } + catch (Exception ignored) { + } } if (updateNeeded) @@ -598,17 +602,22 @@ private ArrayList getSelDownloads() { @Override public Optional getCurrentlySelectedFilm() { - final int selectedTableRow = tabelle.getSelectedRow(); - if (selectedTableRow != -1) { - Optional optRet; - final int modelIndex = tabelle.convertRowIndexToModel(selectedTableRow); - final DatenDownload download = (DatenDownload) tabelle.getModel().getValueAt(modelIndex, DatenDownload.DOWNLOAD_REF); - if (download.film == null) - optRet = Optional.empty(); - else - optRet = Optional.of(download.film); - return optRet; - } else { + try { + final int selectedTableRow = tabelle.getSelectedRow(); + if (selectedTableRow != -1) { + Optional optRet; + int modelIndex = tabelle.convertRowIndexToModel(selectedTableRow); + final DatenDownload download = (DatenDownload) tabelle.getModel().getValueAt(modelIndex, DatenDownload.DOWNLOAD_REF); + if (download.film == null) + optRet = Optional.empty(); + else + optRet = Optional.of(download.film); + return optRet; + } else { + return Optional.empty(); + } + } + catch (Exception e) { return Optional.empty(); } } @@ -948,19 +957,12 @@ public void stopAllWaitingDownloads() { } private void updateFilmData() { - if (isShowing()) { - DatenFilm selectedFilm = null; - final int selectedTableRow = tabelle.getSelectedRow(); - if (selectedTableRow != -1) { - final DatenDownload datenDownload = (DatenDownload) tabelle.getModel().getValueAt(tabelle.convertRowIndexToModel(selectedTableRow), DatenDownload.DOWNLOAD_REF); - if (datenDownload != null) { - selectedFilm = datenDownload.film; - } - } - var infoDialog = mediathekGui.getFilmInfoDialog(); - if (infoDialog != null) { - infoDialog.updateCurrentFilm(selectedFilm); - } + if (!isShowing()) + return; + + var infoDialog = mediathekGui.getFilmInfoDialog(); + if (infoDialog != null) { + infoDialog.updateCurrentFilm(getCurrentlySelectedFilm().orElse(null)); } } From 44eda9027afb9f9425f9d73227bc27a2722aefb5 Mon Sep 17 00:00:00 2001 From: Christian F Date: Thu, 27 Jul 2023 10:44:34 +0200 Subject: [PATCH 002/184] - fix missing context menu for search field - bump kotlin version --- CHANGELOG.md | 1 + pom.xml | 2 +- src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java | 7 +++++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cdb8a2b1c..65da1e0cd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # **14.0.1** - **BUGFIX:** Inkorrekte Beschreibung des "Gespeicherten Film abspielen" Toolbar-Button im Tab Download wurde korrigiert. +- **BUGFIX:** Fehlendes Kontextmenü beim Suchfeld wurde hinzugefügt. # **14.0.0** - Es wird nun Java 20 verwendet. diff --git a/pom.xml b/pom.xml index 64b6c44354..5d39a2461e 100755 --- a/pom.xml +++ b/pom.xml @@ -83,7 +83,7 @@ 20 20 19 - 1.8.21 + 1.9.0 ${jdk.language.version} ${jdk.language.version} diff --git a/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java b/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java index 4241dad0d7..9525c04442 100644 --- a/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java +++ b/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java @@ -799,6 +799,13 @@ public SearchField() { addActionListener(l -> performSearch()); createTrailingComponents(); + + setupContextMenu(); + } + + private void setupContextMenu() { + var handler = new TextCopyPasteHandler<>(this); + setComponentPopupMenu(handler.getPopupMenu()); } protected abstract void createTrailingComponents(); From ae922bd8cd7c069530fc3404948c611e7efb5c42 Mon Sep 17 00:00:00 2001 From: Christian F Date: Sat, 29 Jul 2023 13:54:57 +0200 Subject: [PATCH 003/184] - fixes #711 --- CHANGELOG.md | 1 + .../tabs/tab_film/FilmDescriptionPanel.java | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65da1e0cd9..9568f1fdd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # **14.0.1** - **BUGFIX:** Inkorrekte Beschreibung des "Gespeicherten Film abspielen" Toolbar-Button im Tab Download wurde korrigiert. - **BUGFIX:** Fehlendes Kontextmenü beim Suchfeld wurde hinzugefügt. +- **BUGFIX:** Fehlendes Kontextmenü in der Filmbeschreibung zum Kopieren der URL wurde hinzugefügt. # **14.0.0** - Es wird nun Java 20 verwendet. diff --git a/src/main/java/mediathek/gui/tabs/tab_film/FilmDescriptionPanel.java b/src/main/java/mediathek/gui/tabs/tab_film/FilmDescriptionPanel.java index f0693d3a71..12dc5f2fb9 100644 --- a/src/main/java/mediathek/gui/tabs/tab_film/FilmDescriptionPanel.java +++ b/src/main/java/mediathek/gui/tabs/tab_film/FilmDescriptionPanel.java @@ -17,6 +17,7 @@ import javax.swing.*; import java.awt.*; +import java.awt.event.ActionEvent; import java.net.URI; public class FilmDescriptionPanel extends JPanel { @@ -123,6 +124,7 @@ private void setAllFieldsEmpty() { hyperlink.setVisible(false); hyperlink.setText(""); hyperlink.setToolTipText(""); + hyperlink.setComponentPopupMenu(null); textArea.setText(""); lblIcon.setIcon(null); @@ -139,6 +141,9 @@ private void showFilmDescription(@NotNull DatenFilm film) { hyperlink.setURI(new URI(film.getWebsiteUrl())); hyperlink.setText("Link zur Webseite"); hyperlink.setClicked(false); + JPopupMenu popup = new JPopupMenu(); + popup.add(new CopyToCLipboardAction(film.getWebsiteUrl())); + hyperlink.setComponentPopupMenu(popup); } catch (Exception e) { //logger hyperlink.setText("Link nicht verfügbar"); @@ -150,6 +155,23 @@ private void showFilmDescription(@NotNull DatenFilm film) { lblIcon.setSender(film.getSender()); } + static class CopyToCLipboardAction extends AbstractAction { + private final String webSiteUrl; + + public CopyToCLipboardAction(@NotNull String url) { + webSiteUrl = url; + putValue(Action.NAME, "In Zwischenablage kopieren"); + } + @Override + public void actionPerformed(ActionEvent e) { + try { + GuiFunktionen.copyToClipboard(webSiteUrl); + } + catch (Exception ignored) { + } + } + } + static class SenderIconLabel extends JLabel { private static final Dimension ICON_DIMENSION = new Dimension(96, 96); From ec11213d9b9471fcd3dd05450b75236349b4fe60 Mon Sep 17 00:00:00 2001 From: Christian F Date: Sat, 29 Jul 2023 14:09:49 +0200 Subject: [PATCH 004/184] - fixes #705 --- .install4j/mediathekview_linux.install4j | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.install4j/mediathekview_linux.install4j b/.install4j/mediathekview_linux.install4j index 1cef1ad589..e442e815f5 100644 --- a/.install4j/mediathekview_linux.install4j +++ b/.install4j/mediathekview_linux.install4j @@ -28,7 +28,7 @@ - + @@ -43,7 +43,7 @@ - + From f1579e1dac16e515b32e60fca4c3096ea424403a Mon Sep 17 00:00:00 2001 From: Christian F Date: Sat, 29 Jul 2023 15:27:50 +0200 Subject: [PATCH 005/184] - bump lucene version for Java 20 support --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5d39a2461e..fdbfd7af05 100755 --- a/pom.xml +++ b/pom.xml @@ -142,7 +142,7 @@ ${env.LICENSE_KEY_10} 10.0.5 - 9.5.0 + 9.7.0 From d08fabe270451411ee87c1d9c68449d6aba50675 Mon Sep 17 00:00:00 2001 From: Christian F Date: Sat, 29 Jul 2023 16:56:24 +0200 Subject: [PATCH 006/184] - fixes #711 --- .../gui/filmInformation/InfoDialog.kt | 5 +++++ .../tabs/tab_film/FilmDescriptionPanel.java | 21 ++----------------- .../mediathek/tool/CopyToClipboardAction.kt | 17 +++++++++++++++ 3 files changed, 24 insertions(+), 19 deletions(-) create mode 100644 src/main/java/mediathek/tool/CopyToClipboardAction.kt diff --git a/src/main/java/mediathek/gui/filmInformation/InfoDialog.kt b/src/main/java/mediathek/gui/filmInformation/InfoDialog.kt index ced393bd17..897101c575 100644 --- a/src/main/java/mediathek/gui/filmInformation/InfoDialog.kt +++ b/src/main/java/mediathek/gui/filmInformation/InfoDialog.kt @@ -7,6 +7,7 @@ import mediathek.daten.DatenFilm import mediathek.gui.actions.UrlHyperlinkAction import mediathek.mainwindow.MediathekGui import mediathek.tool.ApplicationConfiguration +import mediathek.tool.CopyToClipboardAction import mediathek.tool.GuiFunktionen import mediathek.tool.SwingErrorDialog import mediathek.tool.sender_icon_cache.MVSenderIconCache @@ -119,6 +120,7 @@ class InfoDialog(parent: Window?) : JDialog(parent) { lblAbo.text = "" hyperlink.toolTipText = "" hyperlink.isEnabled = false + hyperlink.componentPopupMenu = null lblDescription.text = "" SwingUtilities.invokeLater { checkedPack() @@ -157,6 +159,9 @@ class InfoDialog(parent: Window?) : JDialog(parent) { hyperlink.isEnabled = true hyperlink.toolTipText = currentFilm!!.websiteUrl hyperlink.isClicked = false + val popupMenu = JPopupMenu() + popupMenu.add(CopyToClipboardAction(currentFilm!!.websiteUrl)) + hyperlink.componentPopupMenu = popupMenu val desc = currentFilm!!.description.trim { it <= ' ' } lblDescription.text = desc diff --git a/src/main/java/mediathek/gui/tabs/tab_film/FilmDescriptionPanel.java b/src/main/java/mediathek/gui/tabs/tab_film/FilmDescriptionPanel.java index 12dc5f2fb9..a51c48f2e1 100644 --- a/src/main/java/mediathek/gui/tabs/tab_film/FilmDescriptionPanel.java +++ b/src/main/java/mediathek/gui/tabs/tab_film/FilmDescriptionPanel.java @@ -5,6 +5,7 @@ import mediathek.gui.dialog.DialogFilmBeschreibung; import mediathek.gui.tabs.AGuiTabPanel; import mediathek.mainwindow.MediathekGui; +import mediathek.tool.CopyToClipboardAction; import mediathek.tool.GuiFunktionen; import mediathek.tool.sender_icon_cache.MVSenderIconCache; import net.miginfocom.layout.AC; @@ -17,7 +18,6 @@ import javax.swing.*; import java.awt.*; -import java.awt.event.ActionEvent; import java.net.URI; public class FilmDescriptionPanel extends JPanel { @@ -142,7 +142,7 @@ private void showFilmDescription(@NotNull DatenFilm film) { hyperlink.setText("Link zur Webseite"); hyperlink.setClicked(false); JPopupMenu popup = new JPopupMenu(); - popup.add(new CopyToCLipboardAction(film.getWebsiteUrl())); + popup.add(new CopyToClipboardAction(film.getWebsiteUrl())); hyperlink.setComponentPopupMenu(popup); } catch (Exception e) { //logger @@ -155,23 +155,6 @@ private void showFilmDescription(@NotNull DatenFilm film) { lblIcon.setSender(film.getSender()); } - static class CopyToCLipboardAction extends AbstractAction { - private final String webSiteUrl; - - public CopyToCLipboardAction(@NotNull String url) { - webSiteUrl = url; - putValue(Action.NAME, "In Zwischenablage kopieren"); - } - @Override - public void actionPerformed(ActionEvent e) { - try { - GuiFunktionen.copyToClipboard(webSiteUrl); - } - catch (Exception ignored) { - } - } - } - static class SenderIconLabel extends JLabel { private static final Dimension ICON_DIMENSION = new Dimension(96, 96); diff --git a/src/main/java/mediathek/tool/CopyToClipboardAction.kt b/src/main/java/mediathek/tool/CopyToClipboardAction.kt new file mode 100644 index 0000000000..5db3568067 --- /dev/null +++ b/src/main/java/mediathek/tool/CopyToClipboardAction.kt @@ -0,0 +1,17 @@ +package mediathek.tool + +import java.awt.event.ActionEvent +import javax.swing.AbstractAction + +class CopyToClipboardAction(private val webSiteUrl: String) : AbstractAction() { + init { + putValue(NAME, "In Zwischenablage kopieren") + } + + override fun actionPerformed(e: ActionEvent) { + try { + GuiFunktionen.copyToClipboard(webSiteUrl) + } catch (ignored: Exception) { + } + } +} From a21947c54f21696de6785414e6e3af0188421f97 Mon Sep 17 00:00:00 2001 From: Christian F Date: Sat, 5 Aug 2023 16:56:00 +0200 Subject: [PATCH 007/184] - remove unnecessary override --- src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java b/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java index 9525c04442..75ae65e7df 100644 --- a/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java +++ b/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java @@ -831,11 +831,6 @@ public void setSearchMode(SearchControlFieldMode mode) { pcs.firePropertyChange(SEARCHMODE_PROPERTY_STRING, oldValue, mode); } - @Override - protected void fireActionPerformed() { - super.fireActionPerformed(); - } - /** * Clear searchfield on escape key press. */ From cc3e3bf08a0ed22135334496c134c0bb114b45e6 Mon Sep 17 00:00:00 2001 From: Christian F Date: Sat, 5 Aug 2023 17:12:57 +0200 Subject: [PATCH 008/184] - always focus search field after enter event --- CHANGELOG.md | 1 + .../gui/messages/TableModelChangeEvent.java | 9 --------- .../gui/messages/TableModelChangeEvent.kt | 3 +++ .../mediathek/gui/tabs/tab_film/GuiFilme.java | 17 +++++++++++------ .../java/mediathek/mainwindow/MediathekGui.java | 2 +- 5 files changed, 16 insertions(+), 16 deletions(-) delete mode 100644 src/main/java/mediathek/gui/messages/TableModelChangeEvent.java create mode 100644 src/main/java/mediathek/gui/messages/TableModelChangeEvent.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 9568f1fdd7..823e23fc26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ - **BUGFIX:** Inkorrekte Beschreibung des "Gespeicherten Film abspielen" Toolbar-Button im Tab Download wurde korrigiert. - **BUGFIX:** Fehlendes Kontextmenü beim Suchfeld wurde hinzugefügt. - **BUGFIX:** Fehlendes Kontextmenü in der Filmbeschreibung zum Kopieren der URL wurde hinzugefügt. +- **BUGFIX:** Suchfeld wird nach Enter-Taste zum Start der Suche wieder fokussiert. # **14.0.0** - Es wird nun Java 20 verwendet. diff --git a/src/main/java/mediathek/gui/messages/TableModelChangeEvent.java b/src/main/java/mediathek/gui/messages/TableModelChangeEvent.java deleted file mode 100644 index 9c7c35fa35..0000000000 --- a/src/main/java/mediathek/gui/messages/TableModelChangeEvent.java +++ /dev/null @@ -1,9 +0,0 @@ -package mediathek.gui.messages; - -public class TableModelChangeEvent extends BaseEvent { - public boolean active; - - public TableModelChangeEvent(boolean active) { - this.active = active; - } -} diff --git a/src/main/java/mediathek/gui/messages/TableModelChangeEvent.kt b/src/main/java/mediathek/gui/messages/TableModelChangeEvent.kt new file mode 100644 index 0000000000..4a692f79cc --- /dev/null +++ b/src/main/java/mediathek/gui/messages/TableModelChangeEvent.kt @@ -0,0 +1,3 @@ +package mediathek.gui.messages + +data class TableModelChangeEvent(@JvmField val active: Boolean, @JvmField val fromSearchField: Boolean) : BaseEvent() diff --git a/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java b/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java index 75ae65e7df..954c468eb9 100644 --- a/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java +++ b/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java @@ -196,6 +196,8 @@ public void handleTableModelChange(TableModelChangeEvent e) { bookmarkFilmAction.setEnabled(true); toggleFilterDialogVisibilityAction.setEnabled(true); searchField.setEnabled(true); + if (e.fromSearchField) + searchField.requestFocusInWindow(); filterSelectionComboBox.setEnabled(true); }); } @@ -632,7 +634,6 @@ private void setupDataTransitions() { try { SwingUtilities.invokeAndWait(this::loadTable); } catch (InterruptedException | InvocationTargetException ex) { - ex.printStackTrace(); logger.error("Table reload failed", ex); } }); @@ -697,6 +698,10 @@ protected void setupShowFilmDescriptionMenuItem() { } private void loadTable() { + loadTable(false); + } + + private void loadTable(boolean from_search_field) { if (modelFuture != null) { if (!modelFuture.isDone()) { return; @@ -704,7 +709,7 @@ private void loadTable() { } final var messageBus = MessageBus.getMessageBus(); - messageBus.publish(new TableModelChangeEvent(true)); + messageBus.publish(new TableModelChangeEvent(true, from_search_field)); stopBeob = true; tabelle.getSpalten(); @@ -733,7 +738,7 @@ public void onSuccess(TableModel model) { updateFilmData(); stopBeob = false; tabelle.scrollToSelection(); - messageBus.publish(new TableModelChangeEvent(false)); + messageBus.publish(new TableModelChangeEvent(false, from_search_field)); }); } @@ -745,7 +750,7 @@ public void onFailure(@NotNull Throwable thrown) { tabelle.setSpalten(); updateFilmData(); stopBeob = false; - messageBus.publish(new TableModelChangeEvent(false)); + messageBus.publish(new TableModelChangeEvent(false, from_search_field)); }); } }, @@ -971,7 +976,7 @@ protected void performSearch() { luceneSearchHistoryButton.addHistoryEntry(searchText); } - loadTable(); + loadTable(true); } } @@ -1003,7 +1008,7 @@ protected void performSearch() { regularSearchHistoryButton.addHistoryEntry(searchText); } - loadTable(); + loadTable(true); } private void installDocumentListener() { diff --git a/src/main/java/mediathek/mainwindow/MediathekGui.java b/src/main/java/mediathek/mainwindow/MediathekGui.java index e169005c8d..54da7ca149 100644 --- a/src/main/java/mediathek/mainwindow/MediathekGui.java +++ b/src/main/java/mediathek/mainwindow/MediathekGui.java @@ -194,7 +194,7 @@ public MediathekGui() { var messageBus = MessageBus.getMessageBus(); //send before subscribing - messageBus.publishAsync(new TableModelChangeEvent(true)); + messageBus.publishAsync(new TableModelChangeEvent(true, false)); messageBus.subscribe(this); SwingUtilities.invokeLater(() -> { From 3377ddcbbb2e85152e414cf4515b413eb85f6f33 Mon Sep 17 00:00:00 2001 From: Christian F Date: Sat, 5 Aug 2023 17:17:43 +0200 Subject: [PATCH 009/184] Revert "- fixes #705" This reverts commit ec11213d9b9471fcd3dd05450b75236349b4fe60. --- .install4j/mediathekview_linux.install4j | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.install4j/mediathekview_linux.install4j b/.install4j/mediathekview_linux.install4j index e442e815f5..1cef1ad589 100644 --- a/.install4j/mediathekview_linux.install4j +++ b/.install4j/mediathekview_linux.install4j @@ -28,7 +28,7 @@ - + @@ -43,7 +43,7 @@ - + From 031c8b01ad618ec149a6b97c109548bd39de6d14 Mon Sep 17 00:00:00 2001 From: Christian F Date: Sun, 6 Aug 2023 14:41:12 +0200 Subject: [PATCH 010/184] - bump internal version number --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fdbfd7af05..388c414601 100755 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ de.mediathekview MediathekView - 14.0.0 + 14.0.1 jar ${project.groupId}:${project.artifactId} From 05274cc629e279cb52f5cda38bb6034aa69b674d Mon Sep 17 00:00:00 2001 From: Christian F Date: Sun, 6 Aug 2023 16:24:58 +0200 Subject: [PATCH 011/184] - fixes #712 - make icon drawing in list adjustable left or right --- .../allgemein/PanelEinstellungen.java | 17 ++++++++++++++++- .../allgemein/PanelEinstellungen.jfd | 8 ++++++-- .../cellrenderer/CellRendererBaseWithStart.java | 4 ++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/main/java/mediathek/gui/dialogEinstellungen/allgemein/PanelEinstellungen.java b/src/main/java/mediathek/gui/dialogEinstellungen/allgemein/PanelEinstellungen.java index 62b2cc82c1..db361a9765 100644 --- a/src/main/java/mediathek/gui/dialogEinstellungen/allgemein/PanelEinstellungen.java +++ b/src/main/java/mediathek/gui/dialogEinstellungen/allgemein/PanelEinstellungen.java @@ -5,6 +5,7 @@ import mediathek.tool.ApplicationConfiguration; import mediathek.tool.GuiFunktionen; import mediathek.tool.MessageBus; +import mediathek.tool.cellrenderer.CellRendererBaseWithStart; import mediathek.tool.sender_icon_cache.MVSenderIconCache; import net.engio.mbassy.listener.Handler; import net.miginfocom.layout.AC; @@ -140,6 +141,14 @@ public PanelEinstellungen() { cbRestoreSelectedTab.setSelected(restore); cbRestoreSelectedTab.addActionListener(l -> ApplicationConfiguration.getConfiguration().setProperty(ApplicationConfiguration.APPLICATION_RESTORE_SELECTED_TAB, cbRestoreSelectedTab.isSelected())); + + var drawIconsRight = ApplicationConfiguration.getConfiguration() + .getBoolean(CellRendererBaseWithStart.ICON_POSITION_RIGHT, false); + cbDrawListIconsRight.setSelected(drawIconsRight); + cbDrawListIconsRight.addActionListener(l -> { + ApplicationConfiguration.getConfiguration().setProperty(CellRendererBaseWithStart.ICON_POSITION_RIGHT, cbDrawListIconsRight.isSelected()); + MediathekGui.ui().repaint(); + }); } private void setupTabSwitchListener() { @@ -195,6 +204,7 @@ private void initComponents() { jCheckBoxTray = new JCheckBox(); cbUseWikipediaSenderLogos = new JCheckBox(); cbAutomaticUpdateChecks = new JCheckBox(); + cbDrawListIconsRight = new JCheckBox(); modernSearchTitlePanel = new JXTitledPanel(); //======== this ======== @@ -345,6 +355,10 @@ private void initComponents() { //---- cbAutomaticUpdateChecks ---- cbAutomaticUpdateChecks.setText("Programmupdates t\u00e4glich suchen"); //NON-NLS panel1.add(cbAutomaticUpdateChecks); + + //---- cbDrawListIconsRight ---- + cbDrawListIconsRight.setText("Info-Icons der Listen rechts darstellen"); //NON-NLS + panel1.add(cbDrawListIconsRight); } //---- modernSearchTitlePanel ---- @@ -379,7 +393,7 @@ private void initComponents() { .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addComponent(panel1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(modernSearchTitlePanel, GroupLayout.DEFAULT_SIZE, 143, Short.MAX_VALUE) + .addComponent(modernSearchTitlePanel, GroupLayout.DEFAULT_SIZE, 122, Short.MAX_VALUE) .addContainerGap()) ); }// //GEN-END:initComponents @@ -397,6 +411,7 @@ private void initComponents() { private JCheckBox jCheckBoxTray; private JCheckBox cbUseWikipediaSenderLogos; private JCheckBox cbAutomaticUpdateChecks; + private JCheckBox cbDrawListIconsRight; private JXTitledPanel modernSearchTitlePanel; // End of variables declaration//GEN-END:variables } diff --git a/src/main/java/mediathek/gui/dialogEinstellungen/allgemein/PanelEinstellungen.jfd b/src/main/java/mediathek/gui/dialogEinstellungen/allgemein/PanelEinstellungen.jfd index c99291b654..fc48d3e4af 100644 --- a/src/main/java/mediathek/gui/dialogEinstellungen/allgemein/PanelEinstellungen.jfd +++ b/src/main/java/mediathek/gui/dialogEinstellungen/allgemein/PanelEinstellungen.jfd @@ -1,11 +1,11 @@ -JFDML JFormDesigner: "8.0.3.0.246" Java: "17.0.6" encoding: "UTF-8" +JFDML JFormDesigner: "8.1.1.0.298" Java: "17.0.7" encoding: "UTF-8" new FormModel { contentType: "form/swing" root: new FormRoot { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class org.jdesktop.layout.GroupLayout ) { "$horizontalGroup": "par l {seq l {space :::p, par l {comp jPanel3:::::x, comp jPanel5::t:::x, seq {par l {comp jPanel4:::p::p, comp panel1:::p::p}, space :0:20:x}, comp modernSearchTitlePanel::l:::x}, space :::p}}" - "$verticalGroup": "par l {seq l {space :::p, comp jPanel5:::p::p, space :::p, comp jPanel3:::p::p, space :::p, comp jPanel4:::p::p, space :::p, comp panel1:::p::p, space :::p, comp modernSearchTitlePanel::::143:x, space :::p}}" + "$verticalGroup": "par l {seq l {space :::p, comp jPanel5:::p::p, space :::p, comp jPanel3:::p::p, space :::p, comp jPanel4:::p::p, space :::p, comp panel1:::p::p, space :::p, comp modernSearchTitlePanel::::122:x, space :::p}}" } ) { name: "this" "maximumSize": new java.awt.Dimension( 10, 10 ) @@ -136,6 +136,10 @@ new FormModel { name: "cbAutomaticUpdateChecks" "text": "Programmupdates täglich suchen" } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "cbDrawListIconsRight" + "text": "Info-Icons der Listen rechts darstellen" + } ) } ) add( new FormComponent( "org.jdesktop.swingx.JXTitledPanel" ) { name: "modernSearchTitlePanel" diff --git a/src/main/java/mediathek/tool/cellrenderer/CellRendererBaseWithStart.java b/src/main/java/mediathek/tool/cellrenderer/CellRendererBaseWithStart.java index c50f736999..86651e37e9 100644 --- a/src/main/java/mediathek/tool/cellrenderer/CellRendererBaseWithStart.java +++ b/src/main/java/mediathek/tool/cellrenderer/CellRendererBaseWithStart.java @@ -23,6 +23,7 @@ * CellRenderer base class for all custom renderer associated with a Start. */ public class CellRendererBaseWithStart extends CellRendererBase { + public static final String ICON_POSITION_RIGHT = "ui.list.iconposition_right"; private static final EnumSet euCountryList = EnumSet.of(Country.DE, Country.AT, Country.FR); protected final Configuration config = ApplicationConfiguration.getConfiguration(); protected final FlatSVGIcon lockedIcon; @@ -213,6 +214,9 @@ protected void setIndicatorIcons(@NotNull JTable table, @NotNull DatenFilm daten icon = new CompoundIcon(CompoundIcon.Axis.X_AXIS, 3, iconList.toArray(new Icon[0])); setIcon(icon); + final int position = ApplicationConfiguration.getConfiguration() + .getBoolean(ICON_POSITION_RIGHT, false) ? SwingConstants.LEADING : SwingConstants.TRAILING; + setHorizontalTextPosition(position); //always clear at the end iconList.clear(); } From ab0ad89994fc9315bdcba6769dd8c105320d9510 Mon Sep 17 00:00:00 2001 From: Christian F Date: Sun, 6 Aug 2023 16:28:13 +0200 Subject: [PATCH 012/184] - add missing doc --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 823e23fc26..89adfe5ada 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - **BUGFIX:** Fehlendes Kontextmenü beim Suchfeld wurde hinzugefügt. - **BUGFIX:** Fehlendes Kontextmenü in der Filmbeschreibung zum Kopieren der URL wurde hinzugefügt. - **BUGFIX:** Suchfeld wird nach Enter-Taste zum Start der Suche wieder fokussiert. +- **FEATURE:** In der Filmliste kann die Darstellung der Info-Icons nun so konfiguriert werden, dass sie links oder Rechts des Titels dargestellt werden. Dies erfolgt mit der Checkbox unter *Einstellungen/Allgemein->Info-Icons der Listen rechts darstellen*. # **14.0.0** - Es wird nun Java 20 verwendet. From ce06df8cd6a7e37dfbb1b1087e7cdbdaa1388e03 Mon Sep 17 00:00:00 2001 From: Christian F Date: Sun, 6 Aug 2023 17:14:03 +0200 Subject: [PATCH 013/184] - bump kotlin code generation to java 20 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 388c414601..6b4296ccc6 100755 --- a/pom.xml +++ b/pom.xml @@ -82,7 +82,7 @@ UTF-8 20 20 - 19 + 20 1.9.0 ${jdk.language.version} ${jdk.language.version} From 5059df946efc32e5183b2ab041a6d52537721dae Mon Sep 17 00:00:00 2001 From: Christian F Date: Mon, 7 Aug 2023 12:18:37 +0200 Subject: [PATCH 014/184] - fixes #714 - use more animations during change --- CHANGELOG.md | 1 + .../java/mediathek/mac/MediathekGuiMac.kt | 9 + .../mediathek/mainwindow/FontManager.java | 169 ++++++++++++++---- .../mediathek/mainwindow/MediathekGui.java | 33 +--- 4 files changed, 157 insertions(+), 55 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89adfe5ada..091d6e5a8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - **BUGFIX:** Fehlendes Kontextmenü in der Filmbeschreibung zum Kopieren der URL wurde hinzugefügt. - **BUGFIX:** Suchfeld wird nach Enter-Taste zum Start der Suche wieder fokussiert. - **FEATURE:** In der Filmliste kann die Darstellung der Info-Icons nun so konfiguriert werden, dass sie links oder Rechts des Titels dargestellt werden. Dies erfolgt mit der Checkbox unter *Einstellungen/Allgemein->Info-Icons der Listen rechts darstellen*. +- **FEATURE(Windows/Linux):** Geänderte Programmschriftart und -größe wird nun gespeichert und beim Start wiederhergestellt. # **14.0.0** - Es wird nun Java 20 verwendet. diff --git a/src/main/java/mediathek/mac/MediathekGuiMac.kt b/src/main/java/mediathek/mac/MediathekGuiMac.kt index 385c9220a3..a95c3790dc 100644 --- a/src/main/java/mediathek/mac/MediathekGuiMac.kt +++ b/src/main/java/mediathek/mac/MediathekGuiMac.kt @@ -21,6 +21,15 @@ import javax.swing.Box class MediathekGuiMac : MediathekGui() { private val powerManager = OsxPowerManager() + + override fun createFontMenu() { + //unused on macOS + } + + override fun addFontMenu() { + //unused on macOS + } + override fun installAdditionalHelpEntries() { //unused on macOS } diff --git a/src/main/java/mediathek/mainwindow/FontManager.java b/src/main/java/mediathek/mainwindow/FontManager.java index abe985a733..dff5048866 100644 --- a/src/main/java/mediathek/mainwindow/FontManager.java +++ b/src/main/java/mediathek/mainwindow/FontManager.java @@ -3,12 +3,15 @@ import com.formdev.flatlaf.FlatLaf; import com.formdev.flatlaf.extras.FlatAnimatedLafChange; import com.formdev.flatlaf.ui.FlatUIUtils; +import mediathek.tool.ApplicationConfiguration; +import org.apache.commons.configuration2.sync.LockMode; import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.text.StyleContext; import java.awt.*; import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.Arrays; @@ -16,60 +19,157 @@ * Helper class to globally change to L&F font sizes */ public class FontManager { - private final MediathekGui mediathekGui; + private static final String KEY_DEFAULT_FONT = "defaultFont"; + private static final String KEY_LABEL_FONT = "Label.font"; + private static final String CONFIG_DEFAULT_FONT_SIZE = "ui.default_font.size"; + private static final String CONFIG_DEFAULT_FONT_FAMILY = "ui.default_font.family"; private final String[] availableFontFamilyNames; - private int initialFontMenuItemCount = -1; + private final JMenu fontMenu; + private final JMenuItem restoreFontMenuItem = new JMenuItem(); + private final JMenuItem incrFontMenuItem = new JMenuItem(); + private final JMenuItem decrFontMenuItem = new JMenuItem(); + + public FontManager(@NotNull JMenu fontMenu) { + this.fontMenu = fontMenu; - public FontManager(@NotNull MediathekGui mediathekGui) { - this.mediathekGui = mediathekGui; availableFontFamilyNames = GraphicsEnvironment.getLocalGraphicsEnvironment() .getAvailableFontFamilyNames().clone(); Arrays.sort(availableFontFamilyNames); + + initStandardMenuEntries(); + createStandardMenuEntries(); + + updateFontMenuItems(); + } + + private void initStandardMenuEntries() { + restoreFontMenuItem.setText("Schrift zurücksetzen"); + restoreFontMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_0, Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx())); + restoreFontMenuItem.addActionListener(e -> resetFont()); + + incrFontMenuItem.setText("Schrift vergrößern"); + incrFontMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx())); + incrFontMenuItem.addActionListener(e -> increaseFontSize()); + + decrFontMenuItem.setText("Schrift verkleinern"); + decrFontMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx())); + decrFontMenuItem.addActionListener(e -> decreaseFontSize()); + } + + private void createStandardMenuEntries() { + fontMenu.add(restoreFontMenuItem); + fontMenu.add(incrFontMenuItem); + fontMenu.add(decrFontMenuItem); } /** * Reset used L&F font back to default. */ - public void resetFont() { - UIManager.put("defaultFont", null); + private void resetFont() { + FlatAnimatedLafChange.showSnapshot(); + + UIManager.put(KEY_DEFAULT_FONT, null); updateFontMenuItems(); FlatLaf.updateUI(); + + FlatAnimatedLafChange.hideSnapshotWithAnimation(); + + final var config = ApplicationConfiguration.getConfiguration(); + try { + config.lock(LockMode.WRITE); + config.clearProperty(CONFIG_DEFAULT_FONT_SIZE); + config.clearProperty(CONFIG_DEFAULT_FONT_FAMILY); + } finally { + config.unlock(LockMode.WRITE); + } } - public void increaseFontSize() { - Font font = UIManager.getFont("defaultFont"); - Font newFont = font.deriveFont((float) (font.getSize() + 1)); - UIManager.put("defaultFont", newFont); + private void increaseFontSize() { + FlatAnimatedLafChange.showSnapshot(); + + Font font = UIManager.getFont(KEY_DEFAULT_FONT); + final float newFontSize = (float) (font.getSize() + 1); + Font newFont = font.deriveFont(newFontSize); + UIManager.put(KEY_DEFAULT_FONT, newFont); updateFontMenuItems(); FlatLaf.updateUI(); + + FlatAnimatedLafChange.hideSnapshotWithAnimation(); + + writeConfigData(); } - public void decreaseFontSize() { - Font font = UIManager.getFont("defaultFont"); - Font newFont = font.deriveFont((float) Math.max(font.getSize() - 1, 10)); - UIManager.put("defaultFont", newFont); + private void decreaseFontSize() { + FlatAnimatedLafChange.showSnapshot(); + + Font font = UIManager.getFont(KEY_DEFAULT_FONT); + final float newFontSize = (float) Math.max(font.getSize() - 1, 10); + Font newFont = font.deriveFont(newFontSize); + UIManager.put(KEY_DEFAULT_FONT, newFont); updateFontMenuItems(); FlatLaf.updateUI(); + + FlatAnimatedLafChange.hideSnapshotWithAnimation(); + + writeConfigData(); } - public void updateFontMenuItems() { - if (initialFontMenuItemCount < 0) - initialFontMenuItemCount = mediathekGui.fontMenu.getItemCount(); - else { - // remove old font items - for (int i = mediathekGui.fontMenu.getItemCount() - 1; i >= initialFontMenuItemCount; i--) - mediathekGui.fontMenu.remove(i); + /** + * Store the font data in configuration + */ + private void writeConfigData() { + Font currentFont = UIManager.getFont(KEY_LABEL_FONT); + final var currentFamily = currentFont.getFamily(); + final var currentSize = currentFont.getSize(); + + final var config = ApplicationConfiguration.getConfiguration(); + try { + config.lock(LockMode.WRITE); + config.setProperty(CONFIG_DEFAULT_FONT_FAMILY, currentFamily); + config.setProperty(CONFIG_DEFAULT_FONT_SIZE, currentSize); + } finally { + config.unlock(LockMode.WRITE); + } + } + + public void restoreConfigData() { + FlatAnimatedLafChange.showSnapshot(); + + final var config = ApplicationConfiguration.getConfiguration(); + try { + config.lock(LockMode.READ); + final var currentFamily = config.getString(CONFIG_DEFAULT_FONT_FAMILY); + final var currentSize = config.getInt(CONFIG_DEFAULT_FONT_SIZE); + + final Font font = UIManager.getFont(KEY_DEFAULT_FONT); + Font newFont = StyleContext.getDefaultStyleContext().getFont(currentFamily, font.getStyle(), currentSize); + // StyleContext.getFont() may return a UIResource, which would cause loosing user scale factor on Windows + newFont = FlatUIUtils.nonUIResource(newFont); + UIManager.put(KEY_DEFAULT_FONT, newFont); + } + catch (Exception ignored) { } + finally { + config.unlock(LockMode.READ); + } + + FlatLaf.updateUI(); + FlatAnimatedLafChange.hideSnapshotWithAnimation(); + } + + private void updateFontMenuItems() { + fontMenu.removeAll(); + createStandardMenuEntries(); + fontMenu.addSeparator(); // get current font - Font currentFont = UIManager.getFont("Label.font"); + Font currentFont = UIManager.getFont(KEY_LABEL_FONT); String currentFamily = currentFont.getFamily(); String currentSize = Integer.toString(currentFont.getSize()); // add font families - mediathekGui.fontMenu.addSeparator(); ArrayList families = new ArrayList<>(Arrays.asList( "Arial", "Cantarell", "Comic Sans MS", "DejaVu Sans", "Dialog", "Liberation Sans", "Noto Sans", "Roboto", @@ -86,13 +186,13 @@ public void updateFontMenuItems() { JCheckBoxMenuItem item = new JCheckBoxMenuItem(family); item.setSelected(family.equals(currentFamily)); item.addActionListener(this::fontFamilyChanged); - mediathekGui.fontMenu.add(item); + fontMenu.add(item); familiesGroup.add(item); } // add font sizes - mediathekGui.fontMenu.addSeparator(); + fontMenu.addSeparator(); ArrayList sizes = new ArrayList<>(Arrays.asList( "10", "11", "12", "14", "16", "18", "20", "24", "28")); if (!sizes.contains(currentSize)) @@ -104,14 +204,14 @@ public void updateFontMenuItems() { JCheckBoxMenuItem item = new JCheckBoxMenuItem(size); item.setSelected(size.equals(currentSize)); item.addActionListener(this::fontSizeChanged); - mediathekGui.fontMenu.add(item); + fontMenu.add(item); sizesGroup.add(item); } // enabled/disable items boolean enabled = UIManager.getLookAndFeel() instanceof FlatLaf; - for (Component item : mediathekGui.fontMenu.getMenuComponents()) + for (Component item : fontMenu.getMenuComponents()) item.setEnabled(enabled); } @@ -120,23 +220,30 @@ private void fontFamilyChanged(ActionEvent e) { FlatAnimatedLafChange.showSnapshot(); - Font font = UIManager.getFont("defaultFont"); + Font font = UIManager.getFont(KEY_DEFAULT_FONT); Font newFont = StyleContext.getDefaultStyleContext().getFont(fontFamily, font.getStyle(), font.getSize()); // StyleContext.getFont() may return a UIResource, which would cause loosing user scale factor on Windows newFont = FlatUIUtils.nonUIResource(newFont); - UIManager.put("defaultFont", newFont); + UIManager.put(KEY_DEFAULT_FONT, newFont); FlatLaf.updateUI(); FlatAnimatedLafChange.hideSnapshotWithAnimation(); + + writeConfigData(); } private void fontSizeChanged(ActionEvent e) { String fontSizeStr = e.getActionCommand(); - Font font = UIManager.getFont("defaultFont"); + FlatAnimatedLafChange.showSnapshot(); + + Font font = UIManager.getFont(KEY_DEFAULT_FONT); Font newFont = font.deriveFont((float) Integer.parseInt(fontSizeStr)); - UIManager.put("defaultFont", newFont); + UIManager.put(KEY_DEFAULT_FONT, newFont); FlatLaf.updateUI(); + FlatAnimatedLafChange.hideSnapshotWithAnimation(); + + writeConfigData(); } } diff --git a/src/main/java/mediathek/mainwindow/MediathekGui.java b/src/main/java/mediathek/mainwindow/MediathekGui.java index 54da7ca149..0899f82973 100644 --- a/src/main/java/mediathek/mainwindow/MediathekGui.java +++ b/src/main/java/mediathek/mainwindow/MediathekGui.java @@ -52,7 +52,6 @@ import javax.swing.*; import java.awt.*; -import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.IOException; @@ -127,7 +126,7 @@ public class MediathekGui extends JFrame { protected Configuration config = ApplicationConfiguration.getConfiguration(); protected JToolBar commonToolBar = new JToolBar(); protected ManageBookmarkAction manageBookmarkAction = new ManageBookmarkAction(this); - protected FontManager fontManager = new FontManager(this); + protected FontManager fontManager; protected ToggleDarkModeAction toggleDarkModeAction = new ToggleDarkModeAction(); private MVTray tray; private DialogEinstellungen dialogEinstellungen; @@ -411,8 +410,7 @@ private void createMenuBar() { jMenuAbos.setText("Abos"); jMenuBar.add(jMenuAbos); - if (!SystemUtils.IS_OS_MAC_OSX) - jMenuBar.add(fontMenu); + addFontMenu(); jMenuAnsicht.setMnemonic('a'); jMenuAnsicht.setText("Ansicht"); @@ -425,6 +423,10 @@ private void createMenuBar() { setJMenuBar(jMenuBar); } + protected void addFontMenu() { + jMenuBar.add(fontMenu); + } + /** * JavaFX seems to need at least one window shown in order to function without further problems. * This is imminent on macOS, but seems to affect windows as well. @@ -850,26 +852,9 @@ private void createViewMenu() { jMenuAnsicht.add(manageBookmarkAction); } - private void createFontMenu() { - var restoreFontMenuItem = new JMenuItem(); - restoreFontMenuItem.setText("Schrift zurücksetzen"); - restoreFontMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_0, Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx())); - restoreFontMenuItem.addActionListener(e -> fontManager.resetFont()); - fontMenu.add(restoreFontMenuItem); - - var incrFontMenuItem = new JMenuItem(); - incrFontMenuItem.setText("Schrift vergrößern"); - incrFontMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx())); - incrFontMenuItem.addActionListener(e -> fontManager.increaseFontSize()); - fontMenu.add(incrFontMenuItem); - - var decrFontMenuItem = new JMenuItem(); - decrFontMenuItem.setText("Schrift verkleinern"); - decrFontMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx())); - decrFontMenuItem.addActionListener(e -> fontManager.decreaseFontSize()); - fontMenu.add(decrFontMenuItem); - - fontManager.updateFontMenuItems(); + protected void createFontMenu() { + fontManager = new FontManager(fontMenu); + fontManager.restoreConfigData(); } @Handler From a6c7700c6719c775020152065ebf2fafb03ca0d9 Mon Sep 17 00:00:00 2001 From: Christian F Date: Mon, 7 Aug 2023 14:12:28 +0200 Subject: [PATCH 015/184] - update font menu entries after restore data --- src/main/java/mediathek/mainwindow/FontManager.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/mediathek/mainwindow/FontManager.java b/src/main/java/mediathek/mainwindow/FontManager.java index dff5048866..abb4f59659 100644 --- a/src/main/java/mediathek/mainwindow/FontManager.java +++ b/src/main/java/mediathek/mainwindow/FontManager.java @@ -157,6 +157,8 @@ public void restoreConfigData() { FlatLaf.updateUI(); FlatAnimatedLafChange.hideSnapshotWithAnimation(); + + updateFontMenuItems(); } private void updateFontMenuItems() { From 701fd1a7a5ab41219249c73e70e8f22d251fe46d Mon Sep 17 00:00:00 2001 From: Christian F Date: Mon, 7 Aug 2023 14:49:15 +0200 Subject: [PATCH 016/184] - enhance TTML SRT conversion tests - code refactor --- src/main/java/mediathek/tool/MVSubtitle.java | 1 + .../java/mediathek/tool/ttml/StyledString.kt | 3 + src/main/java/mediathek/tool/ttml/Subtitle.kt | 12 +++ .../TimedTextMarkupLanguageParser.java | 48 +++------- .../TimedTextMarkupLanguageParserTest.java | 37 +++++++- src/test/resources/ttml/testcase1.srt | 62 +++++++++++++ src/test/resources/ttml/testcase1.ttml | 90 +++++++++++++++++++ 7 files changed, 212 insertions(+), 41 deletions(-) create mode 100644 src/main/java/mediathek/tool/ttml/StyledString.kt create mode 100644 src/main/java/mediathek/tool/ttml/Subtitle.kt rename src/main/java/mediathek/tool/{ => ttml}/TimedTextMarkupLanguageParser.java (92%) rename src/test/java/mediathek/tool/{ => ttml}/TimedTextMarkupLanguageParserTest.java (73%) create mode 100644 src/test/resources/ttml/testcase1.srt create mode 100644 src/test/resources/ttml/testcase1.ttml diff --git a/src/main/java/mediathek/tool/MVSubtitle.java b/src/main/java/mediathek/tool/MVSubtitle.java index b4095f5f82..513acfad46 100644 --- a/src/main/java/mediathek/tool/MVSubtitle.java +++ b/src/main/java/mediathek/tool/MVSubtitle.java @@ -2,6 +2,7 @@ import mediathek.daten.DatenDownload; import mediathek.tool.http.MVHttpClient; +import mediathek.tool.ttml.TimedTextMarkupLanguageParser; import okhttp3.Request; import okhttp3.Response; import okhttp3.ResponseBody; diff --git a/src/main/java/mediathek/tool/ttml/StyledString.kt b/src/main/java/mediathek/tool/ttml/StyledString.kt new file mode 100644 index 0000000000..c5fafcd82e --- /dev/null +++ b/src/main/java/mediathek/tool/ttml/StyledString.kt @@ -0,0 +1,3 @@ +package mediathek.tool.ttml + +internal data class StyledString( var text: String = "", var color: String = "") diff --git a/src/main/java/mediathek/tool/ttml/Subtitle.kt b/src/main/java/mediathek/tool/ttml/Subtitle.kt new file mode 100644 index 0000000000..9a95ae1523 --- /dev/null +++ b/src/main/java/mediathek/tool/ttml/Subtitle.kt @@ -0,0 +1,12 @@ +package mediathek.tool.ttml + +import java.util.* + +internal class Subtitle { + @JvmField + var begin: Date? = null + @JvmField + var end: Date? = null + @JvmField + val listOfStrings: List = ArrayList() +} diff --git a/src/main/java/mediathek/tool/TimedTextMarkupLanguageParser.java b/src/main/java/mediathek/tool/ttml/TimedTextMarkupLanguageParser.java similarity index 92% rename from src/main/java/mediathek/tool/TimedTextMarkupLanguageParser.java rename to src/main/java/mediathek/tool/ttml/TimedTextMarkupLanguageParser.java index 0a4731bceb..eb9160f7e5 100644 --- a/src/main/java/mediathek/tool/TimedTextMarkupLanguageParser.java +++ b/src/main/java/mediathek/tool/ttml/TimedTextMarkupLanguageParser.java @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package mediathek.tool; +package mediathek.tool.ttml; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -113,9 +113,10 @@ private void buildFilmList() throws Exception { //retrieve the text and color information... final NamedNodeMap attrMap = node.getAttributes(); final Node styleNode = attrMap.getNamedItem("style"); - final StyledString textContent = new StyledString(); + final StyledString textContent = new StyledString(); textContent.setText(node.getTextContent()); + final String col = colorMap.get(styleNode.getNodeValue()); if (col == null) { textContent.setColor(color); // gabs beim BR @@ -157,9 +158,7 @@ private void buildFilmListFlash() throws Exception { if (beginNode != null && endNode != null) { subtitle.begin = parseFlash(beginNode.getNodeValue()); subtitle.end = parseFlash(endNode.getNodeValue()); - final StyledString textContent = new StyledString(); - textContent.setColor(color); // sicher ist sicher - textContent.setText(subnode.getTextContent()); + final StyledString textContent = new StyledString(subnode.getTextContent(), color); final Node col = attrMap.getNamedItem("tts:color"); if (col != null) { @@ -299,12 +298,13 @@ public void toSrt(Path srtFile) { for (Subtitle title : subtitleList) { writer.println(counter); writer.println(srtFormat.format(title.begin) + " --> " + srtFormat.format(title.end)); - for (StyledString entry : title.listOfStrings) { - if (!entry.color.isEmpty()) { - writer.print(""); + for (var entry : title.listOfStrings) { + final var color = entry.getColor(); + if (!color.isEmpty()) { + writer.print(""); } - writer.print(entry.text); - if (!entry.color.isEmpty()) { + writer.print(entry.getText()); + if (!color.isEmpty()) { writer.print(""); } writer.println(); @@ -323,32 +323,4 @@ public void close() { subtitleList.clear(); } - private static class StyledString { - - private String text = ""; - private String color = ""; - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } - - public String getColor() { - return color; - } - - public void setColor(String color) { - this.color = color; - } - } - - private static class Subtitle { - - public Date begin; - public Date end; - public List listOfStrings = new ArrayList<>(); - } } diff --git a/src/test/java/mediathek/tool/TimedTextMarkupLanguageParserTest.java b/src/test/java/mediathek/tool/ttml/TimedTextMarkupLanguageParserTest.java similarity index 73% rename from src/test/java/mediathek/tool/TimedTextMarkupLanguageParserTest.java rename to src/test/java/mediathek/tool/ttml/TimedTextMarkupLanguageParserTest.java index 020e7b2155..0cb9356861 100644 --- a/src/test/java/mediathek/tool/TimedTextMarkupLanguageParserTest.java +++ b/src/test/java/mediathek/tool/ttml/TimedTextMarkupLanguageParserTest.java @@ -1,13 +1,15 @@ -package mediathek.tool; +package mediathek.tool.ttml; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.text.SimpleDateFormat; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; class TimedTextMarkupLanguageParserTest { @Test @@ -68,6 +70,35 @@ void test_aboveHundred() throws Exception { } } + @Test + void convert_ttml_to_srt() { + Path tempSrt = null; + try (TimedTextMarkupLanguageParser parser = new TimedTextMarkupLanguageParser()) { + var file = new File("src/test/resources/ttml/testcase1.ttml"); + var ttmlPath = file.toPath(); + var res = parser.parse(ttmlPath); + assertTrue(res); + + tempSrt = Files.createTempFile("converted_srt_test_case", ".srt"); + parser.toSrt(tempSrt); + + file = new File("src/test/resources/ttml/testcase1.srt"); + var expectedSrtResultPath = file.toPath(); + var mismatch = Files.mismatch(expectedSrtResultPath, tempSrt); + assertEquals(-1L, mismatch); + } catch (IOException e) { + throw new RuntimeException(e); + } + finally { + if (tempSrt != null) { + try { + Files.deleteIfExists(tempSrt); + } catch (IOException ignored) { + } + } + } + } + @Test @DisplayName("Fail for unsupported TTML format") void unsupported_ttml_file_format() { diff --git a/src/test/resources/ttml/testcase1.srt b/src/test/resources/ttml/testcase1.srt new file mode 100644 index 0000000000..c2d384aa87 --- /dev/null +++ b/src/test/resources/ttml/testcase1.srt @@ -0,0 +1,62 @@ +1 +00:00:10,994 --> 00:00:14,474 +Zu Tausenden werden solche +Nachrichten derzeit verschickt. + +2 +00:00:14,514 --> 00:00:18,394 +Der Trick ist simpel, sagt das +Niedersächsische Landeskriminalamt. + +3 +00:00:18,474 --> 00:00:22,034 +Die Kriminellen geben vor die Tochter +oder der Sohn zu sein + +4 +00:00:22,114 --> 00:00:25,834 +und dringend finanzielle Hilfe +und eine Überweisung zu benötigen. + +5 +00:00:25,914 --> 00:00:27,514 +Alles nur als Textnachricht. + +6 +00:00:27,594 --> 00:00:29,514 +Dann wird ein Gespräch aufgebaut. + +7 +00:00:29,594 --> 00:00:32,154 +Es wird Betroffenheit +und Zeitdruck aufgebaut, + +8 +00:00:32,194 --> 00:00:35,794 +weil das Kind ist in Not und +dann machen die Leute das leider. + +9 +00:00:35,834 --> 00:00:38,394 +Oft geht es gleich +um mehrere Tausend Euro. + +10 +00:00:38,514 --> 00:00:41,834 +Insgesamt haben die Betrüger 2022 +allein in Niedersachsen + +11 +00:00:41,914 --> 00:00:43,914 +mehr als 4,5 Mio. Euro erbeutet. + +12 +00:00:43,994 --> 00:00:46,874 +Die Polizei rät in jedem Fall, +skeptisch zu sein + +13 +00:00:46,954 --> 00:00:49,674 +und im Zweifel die Polizei +zu verständigen. + diff --git a/src/test/resources/ttml/testcase1.ttml b/src/test/resources/ttml/testcase1.ttml new file mode 100644 index 0000000000..a5fa84e9e0 --- /dev/null +++ b/src/test/resources/ttml/testcase1.ttml @@ -0,0 +1,90 @@ + + + + +v1.0 + + + + + + + + + + + + + + + + + + + + + + + + +Zu Tausenden werden solche + +Nachrichten derzeit verschickt. + + +Der Trick ist simpel, sagt das + +Niedersächsische Landeskriminalamt. + + +Die Kriminellen geben vor die Tochter + +oder der Sohn zu sein + + +und dringend finanzielle Hilfe + +und eine Überweisung zu benötigen. + + +Alles nur als Textnachricht. + + +Dann wird ein Gespräch aufgebaut. + + +Es wird Betroffenheit + +und Zeitdruck aufgebaut, + + +weil das Kind ist in Not und + +dann machen die Leute das leider. + + +Oft geht es gleich + +um mehrere Tausend Euro. + + +Insgesamt haben die Betrüger 2022 + +allein in Niedersachsen + + +mehr als 4,5 Mio. Euro erbeutet. + + +Die Polizei rät in jedem Fall, + +skeptisch zu sein + + +und im Zweifel die Polizei + +zu verständigen. + + + + From ae66573bb0b500631f6fb292fab2babcf6edb95b Mon Sep 17 00:00:00 2001 From: Christian F Date: Mon, 7 Aug 2023 14:56:53 +0200 Subject: [PATCH 017/184] - add font size 13 --- src/main/java/mediathek/mainwindow/FontManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/mediathek/mainwindow/FontManager.java b/src/main/java/mediathek/mainwindow/FontManager.java index abb4f59659..8725f290ed 100644 --- a/src/main/java/mediathek/mainwindow/FontManager.java +++ b/src/main/java/mediathek/mainwindow/FontManager.java @@ -196,7 +196,7 @@ private void updateFontMenuItems() { // add font sizes fontMenu.addSeparator(); ArrayList sizes = new ArrayList<>(Arrays.asList( - "10", "11", "12", "14", "16", "18", "20", "24", "28")); + "10", "11", "12", "13", "14", "16", "18", "20", "24", "28")); if (!sizes.contains(currentSize)) sizes.add(currentSize); sizes.sort(String.CASE_INSENSITIVE_ORDER); From 105f2073fe1631ec1d1245872c06dcecea6b898e Mon Sep 17 00:00:00 2001 From: Christian F Date: Mon, 7 Aug 2023 15:18:46 +0200 Subject: [PATCH 018/184] - prevent sonar warning --- src/main/java/mediathek/daten/IndexedFilmList.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/mediathek/daten/IndexedFilmList.java b/src/main/java/mediathek/daten/IndexedFilmList.java index df2965371c..27d0925711 100644 --- a/src/main/java/mediathek/daten/IndexedFilmList.java +++ b/src/main/java/mediathek/daten/IndexedFilmList.java @@ -21,9 +21,8 @@ public class IndexedFilmList extends ListeFilme { private IndexSearcher indexSearcher; public IndexedFilmList() { - try { - var fsDir = FSDirectory.open(StandardLocations.getFilmIndexPath()); - luceneDirectory = new NRTCachingDirectory(fsDir, 20.0, 100.0); + try { + luceneDirectory = new NRTCachingDirectory(FSDirectory.open(StandardLocations.getFilmIndexPath()), 20.0, 100.0); IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer); indexWriterConfig.setRAMBufferSizeMB(256d); From 8db21448065e22027d9b630cb2829b3f56500d71 Mon Sep 17 00:00:00 2001 From: Christian F Date: Mon, 7 Aug 2023 15:28:44 +0200 Subject: [PATCH 019/184] - satisfy analyzer warning --- .../tool/ttml/TimedTextMarkupLanguageParser.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/mediathek/tool/ttml/TimedTextMarkupLanguageParser.java b/src/main/java/mediathek/tool/ttml/TimedTextMarkupLanguageParser.java index eb9160f7e5..b137833cf7 100644 --- a/src/main/java/mediathek/tool/ttml/TimedTextMarkupLanguageParser.java +++ b/src/main/java/mediathek/tool/ttml/TimedTextMarkupLanguageParser.java @@ -299,12 +299,12 @@ public void toSrt(Path srtFile) { writer.println(counter); writer.println(srtFormat.format(title.begin) + " --> " + srtFormat.format(title.end)); for (var entry : title.listOfStrings) { - final var color = entry.getColor(); - if (!color.isEmpty()) { - writer.print(""); + final var entryColor = entry.getColor(); + if (!entryColor.isEmpty()) { + writer.print(""); } writer.print(entry.getText()); - if (!color.isEmpty()) { + if (!entryColor.isEmpty()) { writer.print(""); } writer.println(); From 2e3e87594fb74a434ba12cb08a92c13d43775b5b Mon Sep 17 00:00:00 2001 From: Christian F Date: Mon, 7 Aug 2023 17:41:58 +0200 Subject: [PATCH 020/184] - for combobox to be not editable. --- src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java b/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java index 954c468eb9..9ea16e823f 100644 --- a/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java +++ b/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java @@ -168,9 +168,13 @@ private void createToolBar() { toolBar.add(saveFilmAction); toolBar.add(bookmarkFilmAction); toolBar.addSeparator(); + filterSelectionComboBox.setMaximumSize(new Dimension(150, 100)); + filterSelectionComboBox.setEditable(false); + filterSelectionComboBox.setToolTipText("Aktiver Filter"); toolBar.add(filterSelectionComboBox); toolBar.addSeparator(); + toolBar.add(new JLabel("Suche:")); toolBar.add(searchField); toolBar.addSeparator(); From 8401bc7015bb1748eab8de82cbe2472bcda9631a Mon Sep 17 00:00:00 2001 From: Christian F Date: Mon, 7 Aug 2023 18:02:08 +0200 Subject: [PATCH 021/184] - prevent user from switching blacklist while lucene indexing is in progress --- .../java/mediathek/gui/tasks/LuceneIndexWorker.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/mediathek/gui/tasks/LuceneIndexWorker.java b/src/main/java/mediathek/gui/tasks/LuceneIndexWorker.java index 9845a55691..34f2768eab 100644 --- a/src/main/java/mediathek/gui/tasks/LuceneIndexWorker.java +++ b/src/main/java/mediathek/gui/tasks/LuceneIndexWorker.java @@ -29,6 +29,11 @@ public LuceneIndexWorker(@NotNull JLabel progLabel, @NotNull JProgressBar progre this.progLabel = progLabel; SwingUtilities.invokeLater(() -> { + final var ui = MediathekGui.ui(); + ui.toggleBlacklistAction.setEnabled(false); + ui.editBlacklistAction.setEnabled(false); + ui.loadFilmListAction.setEnabled(false); + progLabel.setText("Blacklist anwenden"); progressBar.setIndeterminate(true); }); @@ -118,4 +123,12 @@ protected Void doInBackground() { return null; } + @Override + protected void done() { + final var ui = MediathekGui.ui(); + ui.toggleBlacklistAction.setEnabled(true); + ui.editBlacklistAction.setEnabled(true); + ui.loadFilmListAction.setEnabled(true); + } + } From 69983349833ecf2859069062122d31a83cadf018 Mon Sep 17 00:00:00 2001 From: Christian F Date: Mon, 7 Aug 2023 18:03:12 +0200 Subject: [PATCH 022/184] - add doc --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 091d6e5a8e..95d36d2a27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - **BUGFIX:** Fehlendes Kontextmenü beim Suchfeld wurde hinzugefügt. - **BUGFIX:** Fehlendes Kontextmenü in der Filmbeschreibung zum Kopieren der URL wurde hinzugefügt. - **BUGFIX:** Suchfeld wird nach Enter-Taste zum Start der Suche wieder fokussiert. +- **BUGFIX:** Programm stürzt nicht mehr ab wenn man versucht während der Indizierung die Blacklist auszuschalten. - **FEATURE:** In der Filmliste kann die Darstellung der Info-Icons nun so konfiguriert werden, dass sie links oder Rechts des Titels dargestellt werden. Dies erfolgt mit der Checkbox unter *Einstellungen/Allgemein->Info-Icons der Listen rechts darstellen*. - **FEATURE(Windows/Linux):** Geänderte Programmschriftart und -größe wird nun gespeichert und beim Start wiederhergestellt. From 06f984a767a6ffc76dda0b35ed2074274f177264 Mon Sep 17 00:00:00 2001 From: Christian F Date: Mon, 7 Aug 2023 19:42:42 +0200 Subject: [PATCH 023/184] - fixes #622 --- .../mediathek/gui/tabs/tab_film/GuiFilme.java | 15 ++++++++---- .../mediathek/mainwindow/MediathekGui.java | 23 +++++++++++++++---- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java b/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java index 9ea16e823f..6edc1548d1 100644 --- a/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java +++ b/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java @@ -95,6 +95,8 @@ public class GuiFilme extends AGuiTabPanel { public final PlayFilmAction playFilmAction = new PlayFilmAction(this); public final SaveFilmAction saveFilmAction = new SaveFilmAction(); public final BookmarkFilmAction bookmarkFilmAction = new BookmarkFilmAction(); + public final CopyUrlToClipboardAction copyHqUrlToClipboardAction = new CopyUrlToClipboardAction(FilmResolution.Enum.HIGH_QUALITY); + public final CopyUrlToClipboardAction copyNormalUrlToClipboardAction = new CopyUrlToClipboardAction(FilmResolution.Enum.NORMAL); protected final JTabbedPane psetButtonsTab = new JTabbedPane(); private final PauseTransition reloadTableDataTransition = new PauseTransition(Duration.millis(250d)); private final MarkFilmAsSeenAction markFilmAsSeenAction = new MarkFilmAsSeenAction(); @@ -346,8 +348,8 @@ private void setupKeyMapping() { actionMap.put(ACTION_MAP_KEY_PLAY_FILM, playFilmAction); actionMap.put(ACTION_MAP_KEY_SAVE_FILM, saveFilmAction); actionMap.put(ACTION_MAP_KEY_BOOKMARK_FILM, bookmarkFilmAction); - actionMap.put(ACTION_MAP_KEY_COPY_NORMAL_URL, new CopyUrlToClipboardAction(FilmResolution.Enum.NORMAL)); - actionMap.put(ACTION_MAP_KEY_COPY_HD_URL, new CopyUrlToClipboardAction(FilmResolution.Enum.HIGH_QUALITY)); + actionMap.put(ACTION_MAP_KEY_COPY_NORMAL_URL, copyNormalUrlToClipboardAction); + actionMap.put(ACTION_MAP_KEY_COPY_HD_URL, copyHqUrlToClipboardAction); actionMap.put(ACTION_MAP_KEY_COPY_KLEIN_URL, new CopyUrlToClipboardAction(FilmResolution.Enum.LOW)); actionMap.put(ACTION_MAP_KEY_MARK_SEEN, markFilmAsSeenAction); actionMap.put(ACTION_MAP_KEY_MARK_UNSEEN, markFilmAsUnseenAction); @@ -761,7 +763,7 @@ public void onFailure(@NotNull Throwable thrown) { decoratedPool); } - static class FilterVisibilityToggleButton extends JToggleButton { + static public class FilterVisibilityToggleButton extends JToggleButton { public FilterVisibilityToggleButton(Action a) { super(a); setText(""); @@ -1169,7 +1171,7 @@ public void actionPerformed(ActionEvent e) { } } - private class CopyUrlToClipboardAction extends AbstractAction { + public class CopyUrlToClipboardAction extends AbstractAction { private final FilmResolution.Enum resolution; CopyUrlToClipboardAction(FilmResolution.Enum resolution) { @@ -1457,6 +1459,8 @@ private void setupFilmUrlCopyToClipboardEntries(@NotNull JMenu parentMenu, @NotN // HD if (!uHd.isEmpty()) { item = new JMenuItem("höchste/hohe Qualität"); + item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, GuiFunktionen.getPlatformControlKey() | + KeyEvent.SHIFT_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)); item.addActionListener( e -> GuiFunktionen.copyToClipboard(film.getUrlFuerAufloesung(FilmResolution.Enum.HIGH_QUALITY))); submenueURL.add(item); @@ -1465,6 +1469,9 @@ private void setupFilmUrlCopyToClipboardEntries(@NotNull JMenu parentMenu, @NotN // normale Auflösung, gibts immer item = new JMenuItem("mittlere Qualität"); item.addActionListener(copyNormalUrlListener); + item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, GuiFunktionen.getPlatformControlKey() | + KeyEvent.SHIFT_DOWN_MASK | KeyEvent.ALT_DOWN_MASK)); + submenueURL.add(item); // kleine Auflösung diff --git a/src/main/java/mediathek/mainwindow/MediathekGui.java b/src/main/java/mediathek/mainwindow/MediathekGui.java index 0899f82973..ed2e9f2103 100644 --- a/src/main/java/mediathek/mainwindow/MediathekGui.java +++ b/src/main/java/mediathek/mainwindow/MediathekGui.java @@ -52,6 +52,7 @@ import javax.swing.*; import java.awt.*; +import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.IOException; @@ -76,6 +77,8 @@ public class MediathekGui extends JFrame { private static final String NONE = "none"; private static final int MIN_WINDOW_WIDTH = 800; private static final int MIN_WINDOW_HEIGHT = 600; + private static final String ACTION_MAP_KEY_COPY_HQ_URL = "COPY_HQ_URL"; + private static final String ACTION_MAP_KEY_COPY_NORMAL_URL = "COPY_NORMAL_URL"; /** * "Pointer" to UI */ @@ -137,7 +140,6 @@ public class MediathekGui extends JFrame { private IndicatorThread progressIndicatorThread; private AutomaticFilmlistUpdate automaticFilmlistUpdate; private boolean shutdownRequested; - public MediathekGui() { ui = this; @@ -222,6 +224,8 @@ public MediathekGui() { logger.trace("Loading info dialog"); filmInfo = new InfoDialog(this); logger.trace("Finished loading info dialog"); + + mapFilmUrlCopyCommands(); } /** @@ -233,6 +237,18 @@ public static MediathekGui ui() { return ui; } + private void mapFilmUrlCopyCommands() { + final var im = jMenuBar.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); + im.put(KeyStroke.getKeyStroke(KeyEvent.VK_H, GuiFunktionen.getPlatformControlKey() | + KeyEvent.SHIFT_DOWN_MASK | KeyEvent.ALT_DOWN_MASK), ACTION_MAP_KEY_COPY_HQ_URL); + im.put(KeyStroke.getKeyStroke(KeyEvent.VK_N, GuiFunktionen.getPlatformControlKey() | + KeyEvent.SHIFT_DOWN_MASK | KeyEvent.ALT_DOWN_MASK), ACTION_MAP_KEY_COPY_NORMAL_URL); + + final var am = jMenuBar.getActionMap(); + am.put(ACTION_MAP_KEY_COPY_HQ_URL, tabFilme.copyHqUrlToClipboardAction); + am.put(ACTION_MAP_KEY_COPY_NORMAL_URL, tabFilme.copyNormalUrlToClipboardAction); + } + protected void setupScrollBarWidth() { // win and linux users complain about scrollbars being too small... UIManager.put( "ScrollBar.width", 16 ); @@ -1059,7 +1075,7 @@ private void cleanupLuceneIndex() { writer.commit(); //filmList.getLuceneDirectory().close(); } catch (Exception ex) { - ex.printStackTrace(); + logger.error("cleanupLuceneIndex error", ex); } } } @@ -1105,8 +1121,7 @@ private void waitForCommonPoolToComplete() { try { logger.debug("POOL SUBMISSIONS: {}", ForkJoinPool.commonPool().getQueuedSubmissionCount()); TimeUnit.MILLISECONDS.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); + } catch (InterruptedException ignored) { } } From 79bbf0e639718d936e2bf9def66dcef682c93138 Mon Sep 17 00:00:00 2001 From: Christian F Date: Mon, 7 Aug 2023 19:46:59 +0200 Subject: [PATCH 024/184] - add doc --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95d36d2a27..c2dd5c81b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - **BUGFIX:** Programm stürzt nicht mehr ab wenn man versucht während der Indizierung die Blacklist auszuschalten. - **FEATURE:** In der Filmliste kann die Darstellung der Info-Icons nun so konfiguriert werden, dass sie links oder Rechts des Titels dargestellt werden. Dies erfolgt mit der Checkbox unter *Einstellungen/Allgemein->Info-Icons der Listen rechts darstellen*. - **FEATURE(Windows/Linux):** Geänderte Programmschriftart und -größe wird nun gespeichert und beim Start wiederhergestellt. +- **FEATURE:** Die URLs des selektierten Films können nun für HQ und normale Auflösung mittels `Strg+Alt+Shift+H` bzw. `Strg+Alt+Shift+N` oder wie bisher über das Kontextmenü in die Zwischenablage kopiert werden. Unter macOS ersetze `Strg` mit `Command`. # **14.0.0** - Es wird nun Java 20 verwendet. From e7da36c8e59a30c4fe57db2e36ff3e261137643e Mon Sep 17 00:00:00 2001 From: Christian F Date: Mon, 7 Aug 2023 22:38:02 +0200 Subject: [PATCH 025/184] - export film line info to clipboard as json --- .../mediathek/gui/tabs/tab_film/GuiFilme.java | 75 +++++++++++++++++++ .../mediathek/mainwindow/MediathekGui.java | 4 + 2 files changed, 79 insertions(+) diff --git a/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java b/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java index 6edc1548d1..2013c81504 100644 --- a/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java +++ b/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java @@ -74,6 +74,7 @@ import java.util.Optional; import java.util.function.Consumer; import java.util.function.IntConsumer; +import java.util.stream.Collectors; public class GuiFilme extends AGuiTabPanel { @@ -97,6 +98,7 @@ public class GuiFilme extends AGuiTabPanel { public final BookmarkFilmAction bookmarkFilmAction = new BookmarkFilmAction(); public final CopyUrlToClipboardAction copyHqUrlToClipboardAction = new CopyUrlToClipboardAction(FilmResolution.Enum.HIGH_QUALITY); public final CopyUrlToClipboardAction copyNormalUrlToClipboardAction = new CopyUrlToClipboardAction(FilmResolution.Enum.NORMAL); + public final CopyFilmLineInfoToClipboardAction copyFilmLineInfoToClipboardAction = new CopyFilmLineInfoToClipboardAction(); protected final JTabbedPane psetButtonsTab = new JTabbedPane(); private final PauseTransition reloadTableDataTransition = new PauseTransition(Duration.millis(250d)); private final MarkFilmAsSeenAction markFilmAsSeenAction = new MarkFilmAsSeenAction(); @@ -1171,6 +1173,79 @@ public void actionPerformed(ActionEvent e) { } } + public class CopyFilmLineInfoToClipboardAction extends AbstractAction { + + @Override + public void actionPerformed(ActionEvent e) { + Optional filmSelection = getCurrentlySelectedFilm(); + filmSelection.ifPresent( + film -> { + try { + JsonFilmObject filmObject = new JsonFilmObject(); + filmObject.sender = film.getSender(); + filmObject.thema = film.getThema(); + filmObject.titel = film.getTitle(); + filmObject.sende_datum = film.getSendeDatum(); + //sende_zeit + String strZeit = film.getSendeZeit(); + final int len = strZeit.length(); + + if (strZeit.isEmpty() || len < 8) + filmObject.sende_zeit = ""; + else { + strZeit = strZeit.substring(0, len - 3); + filmObject.sende_zeit = strZeit; + } + + filmObject.laenge = film.getFilmLengthAsString(); + filmObject.groesse = film.getFileSize().toString(); + filmObject.beschreibung = film.getDescription(); + filmObject.url_normal = film.getUrlNormalQuality(); + filmObject.url_website = film.getWebsiteUrl(); + filmObject.url_subtitle = film.getSubtitleUrl(); + String url = film.getLowQualityUrl(); + if (DatenFilm.isCompressedUrl(url)) + url = film.decompressUrl(url); + filmObject.url_low_quality = url; + + url = film.getHighQualityUrl(); + if (DatenFilm.isCompressedUrl(url)) + url = film.decompressUrl(url); + filmObject.url_high_quality = url; + + filmObject.datum_long = film.getDatumLong(); + if (film.countrySet.isEmpty()) + filmObject.geo = ""; + else + filmObject.geo = film.countrySet.stream().map(Country::toString).collect(Collectors.joining("-")); + + String result = new ObjectMapper().writeValueAsString(filmObject); + GuiFunktionen.copyToClipboard(result); + } catch (JsonProcessingException ex) { + logger.error("Failed to export film line info", ex); + } + }); + } + + static class JsonFilmObject { + public String sender; + public String thema; + public String titel; + public String sende_datum; + public String sende_zeit; + public String laenge; + public String groesse; + public String geo; + public String url_normal; + public String url_low_quality; + public String url_high_quality; + public String url_subtitle; + public String url_website; + public String beschreibung; + public String datum_long; + } + } + public class CopyUrlToClipboardAction extends AbstractAction { private final FilmResolution.Enum resolution; diff --git a/src/main/java/mediathek/mainwindow/MediathekGui.java b/src/main/java/mediathek/mainwindow/MediathekGui.java index ed2e9f2103..90e97d9448 100644 --- a/src/main/java/mediathek/mainwindow/MediathekGui.java +++ b/src/main/java/mediathek/mainwindow/MediathekGui.java @@ -79,6 +79,7 @@ public class MediathekGui extends JFrame { private static final int MIN_WINDOW_HEIGHT = 600; private static final String ACTION_MAP_KEY_COPY_HQ_URL = "COPY_HQ_URL"; private static final String ACTION_MAP_KEY_COPY_NORMAL_URL = "COPY_NORMAL_URL"; + private static final String ACTION_MAP_COPY_FILM_LINE_INFO = "COPY_FILM_LINE_INFO"; /** * "Pointer" to UI */ @@ -243,10 +244,13 @@ private void mapFilmUrlCopyCommands() { KeyEvent.SHIFT_DOWN_MASK | KeyEvent.ALT_DOWN_MASK), ACTION_MAP_KEY_COPY_HQ_URL); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_N, GuiFunktionen.getPlatformControlKey() | KeyEvent.SHIFT_DOWN_MASK | KeyEvent.ALT_DOWN_MASK), ACTION_MAP_KEY_COPY_NORMAL_URL); + im.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, GuiFunktionen.getPlatformControlKey() | + KeyEvent.SHIFT_DOWN_MASK | KeyEvent.ALT_DOWN_MASK), ACTION_MAP_COPY_FILM_LINE_INFO); final var am = jMenuBar.getActionMap(); am.put(ACTION_MAP_KEY_COPY_HQ_URL, tabFilme.copyHqUrlToClipboardAction); am.put(ACTION_MAP_KEY_COPY_NORMAL_URL, tabFilme.copyNormalUrlToClipboardAction); + am.put(ACTION_MAP_COPY_FILM_LINE_INFO, tabFilme.copyFilmLineInfoToClipboardAction); } protected void setupScrollBarWidth() { From 6c1a8c31597ed74f385142c6d010f3e6459b74c0 Mon Sep 17 00:00:00 2001 From: Christian F Date: Tue, 8 Aug 2023 09:09:30 +0200 Subject: [PATCH 026/184] Revert "- export film line info to clipboard as json" This reverts commit e7da36c8e59a30c4fe57db2e36ff3e261137643e. --- .../mediathek/gui/tabs/tab_film/GuiFilme.java | 75 ------------------- .../mediathek/mainwindow/MediathekGui.java | 4 - 2 files changed, 79 deletions(-) diff --git a/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java b/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java index 2013c81504..6edc1548d1 100644 --- a/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java +++ b/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java @@ -74,7 +74,6 @@ import java.util.Optional; import java.util.function.Consumer; import java.util.function.IntConsumer; -import java.util.stream.Collectors; public class GuiFilme extends AGuiTabPanel { @@ -98,7 +97,6 @@ public class GuiFilme extends AGuiTabPanel { public final BookmarkFilmAction bookmarkFilmAction = new BookmarkFilmAction(); public final CopyUrlToClipboardAction copyHqUrlToClipboardAction = new CopyUrlToClipboardAction(FilmResolution.Enum.HIGH_QUALITY); public final CopyUrlToClipboardAction copyNormalUrlToClipboardAction = new CopyUrlToClipboardAction(FilmResolution.Enum.NORMAL); - public final CopyFilmLineInfoToClipboardAction copyFilmLineInfoToClipboardAction = new CopyFilmLineInfoToClipboardAction(); protected final JTabbedPane psetButtonsTab = new JTabbedPane(); private final PauseTransition reloadTableDataTransition = new PauseTransition(Duration.millis(250d)); private final MarkFilmAsSeenAction markFilmAsSeenAction = new MarkFilmAsSeenAction(); @@ -1173,79 +1171,6 @@ public void actionPerformed(ActionEvent e) { } } - public class CopyFilmLineInfoToClipboardAction extends AbstractAction { - - @Override - public void actionPerformed(ActionEvent e) { - Optional filmSelection = getCurrentlySelectedFilm(); - filmSelection.ifPresent( - film -> { - try { - JsonFilmObject filmObject = new JsonFilmObject(); - filmObject.sender = film.getSender(); - filmObject.thema = film.getThema(); - filmObject.titel = film.getTitle(); - filmObject.sende_datum = film.getSendeDatum(); - //sende_zeit - String strZeit = film.getSendeZeit(); - final int len = strZeit.length(); - - if (strZeit.isEmpty() || len < 8) - filmObject.sende_zeit = ""; - else { - strZeit = strZeit.substring(0, len - 3); - filmObject.sende_zeit = strZeit; - } - - filmObject.laenge = film.getFilmLengthAsString(); - filmObject.groesse = film.getFileSize().toString(); - filmObject.beschreibung = film.getDescription(); - filmObject.url_normal = film.getUrlNormalQuality(); - filmObject.url_website = film.getWebsiteUrl(); - filmObject.url_subtitle = film.getSubtitleUrl(); - String url = film.getLowQualityUrl(); - if (DatenFilm.isCompressedUrl(url)) - url = film.decompressUrl(url); - filmObject.url_low_quality = url; - - url = film.getHighQualityUrl(); - if (DatenFilm.isCompressedUrl(url)) - url = film.decompressUrl(url); - filmObject.url_high_quality = url; - - filmObject.datum_long = film.getDatumLong(); - if (film.countrySet.isEmpty()) - filmObject.geo = ""; - else - filmObject.geo = film.countrySet.stream().map(Country::toString).collect(Collectors.joining("-")); - - String result = new ObjectMapper().writeValueAsString(filmObject); - GuiFunktionen.copyToClipboard(result); - } catch (JsonProcessingException ex) { - logger.error("Failed to export film line info", ex); - } - }); - } - - static class JsonFilmObject { - public String sender; - public String thema; - public String titel; - public String sende_datum; - public String sende_zeit; - public String laenge; - public String groesse; - public String geo; - public String url_normal; - public String url_low_quality; - public String url_high_quality; - public String url_subtitle; - public String url_website; - public String beschreibung; - public String datum_long; - } - } - public class CopyUrlToClipboardAction extends AbstractAction { private final FilmResolution.Enum resolution; diff --git a/src/main/java/mediathek/mainwindow/MediathekGui.java b/src/main/java/mediathek/mainwindow/MediathekGui.java index 90e97d9448..ed2e9f2103 100644 --- a/src/main/java/mediathek/mainwindow/MediathekGui.java +++ b/src/main/java/mediathek/mainwindow/MediathekGui.java @@ -79,7 +79,6 @@ public class MediathekGui extends JFrame { private static final int MIN_WINDOW_HEIGHT = 600; private static final String ACTION_MAP_KEY_COPY_HQ_URL = "COPY_HQ_URL"; private static final String ACTION_MAP_KEY_COPY_NORMAL_URL = "COPY_NORMAL_URL"; - private static final String ACTION_MAP_COPY_FILM_LINE_INFO = "COPY_FILM_LINE_INFO"; /** * "Pointer" to UI */ @@ -244,13 +243,10 @@ private void mapFilmUrlCopyCommands() { KeyEvent.SHIFT_DOWN_MASK | KeyEvent.ALT_DOWN_MASK), ACTION_MAP_KEY_COPY_HQ_URL); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_N, GuiFunktionen.getPlatformControlKey() | KeyEvent.SHIFT_DOWN_MASK | KeyEvent.ALT_DOWN_MASK), ACTION_MAP_KEY_COPY_NORMAL_URL); - im.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, GuiFunktionen.getPlatformControlKey() | - KeyEvent.SHIFT_DOWN_MASK | KeyEvent.ALT_DOWN_MASK), ACTION_MAP_COPY_FILM_LINE_INFO); final var am = jMenuBar.getActionMap(); am.put(ACTION_MAP_KEY_COPY_HQ_URL, tabFilme.copyHqUrlToClipboardAction); am.put(ACTION_MAP_KEY_COPY_NORMAL_URL, tabFilme.copyNormalUrlToClipboardAction); - am.put(ACTION_MAP_COPY_FILM_LINE_INFO, tabFilme.copyFilmLineInfoToClipboardAction); } protected void setupScrollBarWidth() { From 69766b96487e27c86a7c2b6a290bfde90bd265cb Mon Sep 17 00:00:00 2001 From: Christian F Date: Tue, 8 Aug 2023 09:28:18 +0200 Subject: [PATCH 027/184] - correctly adjust row height of JTable during font changes --- CHANGELOG.md | 1 + .../gui/messages/FontSizeChangedEvent.java | 4 ++++ .../java/mediathek/mainwindow/FontManager.java | 15 +++++++++++++++ src/main/java/mediathek/tool/table/MVTable.java | 11 +++++++++++ 4 files changed, 31 insertions(+) create mode 100644 src/main/java/mediathek/gui/messages/FontSizeChangedEvent.java diff --git a/CHANGELOG.md b/CHANGELOG.md index c2dd5c81b3..13002fcc11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - **BUGFIX:** Fehlendes Kontextmenü in der Filmbeschreibung zum Kopieren der URL wurde hinzugefügt. - **BUGFIX:** Suchfeld wird nach Enter-Taste zum Start der Suche wieder fokussiert. - **BUGFIX:** Programm stürzt nicht mehr ab wenn man versucht während der Indizierung die Blacklist auszuschalten. +- **BUGFIX(Windows/Linux):** Zeilenhöhe der Tabellen wird nun nach Änderung der Schriftart und -größe korrekt justiert. - **FEATURE:** In der Filmliste kann die Darstellung der Info-Icons nun so konfiguriert werden, dass sie links oder Rechts des Titels dargestellt werden. Dies erfolgt mit der Checkbox unter *Einstellungen/Allgemein->Info-Icons der Listen rechts darstellen*. - **FEATURE(Windows/Linux):** Geänderte Programmschriftart und -größe wird nun gespeichert und beim Start wiederhergestellt. - **FEATURE:** Die URLs des selektierten Films können nun für HQ und normale Auflösung mittels `Strg+Alt+Shift+H` bzw. `Strg+Alt+Shift+N` oder wie bisher über das Kontextmenü in die Zwischenablage kopiert werden. Unter macOS ersetze `Strg` mit `Command`. diff --git a/src/main/java/mediathek/gui/messages/FontSizeChangedEvent.java b/src/main/java/mediathek/gui/messages/FontSizeChangedEvent.java new file mode 100644 index 0000000000..d73be4383e --- /dev/null +++ b/src/main/java/mediathek/gui/messages/FontSizeChangedEvent.java @@ -0,0 +1,4 @@ +package mediathek.gui.messages; + +public class FontSizeChangedEvent extends BaseEvent { +} diff --git a/src/main/java/mediathek/mainwindow/FontManager.java b/src/main/java/mediathek/mainwindow/FontManager.java index 8725f290ed..34ce07c281 100644 --- a/src/main/java/mediathek/mainwindow/FontManager.java +++ b/src/main/java/mediathek/mainwindow/FontManager.java @@ -3,7 +3,9 @@ import com.formdev.flatlaf.FlatLaf; import com.formdev.flatlaf.extras.FlatAnimatedLafChange; import com.formdev.flatlaf.ui.FlatUIUtils; +import mediathek.gui.messages.FontSizeChangedEvent; import mediathek.tool.ApplicationConfiguration; +import mediathek.tool.MessageBus; import org.apache.commons.configuration2.sync.LockMode; import org.jetbrains.annotations.NotNull; @@ -82,6 +84,8 @@ private void resetFont() { } finally { config.unlock(LockMode.WRITE); } + + MessageBus.getMessageBus().publishAsync(new FontSizeChangedEvent()); } private void increaseFontSize() { @@ -98,6 +102,8 @@ private void increaseFontSize() { FlatAnimatedLafChange.hideSnapshotWithAnimation(); writeConfigData(); + + MessageBus.getMessageBus().publishAsync(new FontSizeChangedEvent()); } private void decreaseFontSize() { @@ -114,6 +120,9 @@ private void decreaseFontSize() { FlatAnimatedLafChange.hideSnapshotWithAnimation(); writeConfigData(); + + + MessageBus.getMessageBus().publishAsync(new FontSizeChangedEvent()); } /** @@ -232,6 +241,9 @@ private void fontFamilyChanged(ActionEvent e) { FlatAnimatedLafChange.hideSnapshotWithAnimation(); writeConfigData(); + + + MessageBus.getMessageBus().publishAsync(new FontSizeChangedEvent()); } private void fontSizeChanged(ActionEvent e) { @@ -247,5 +259,8 @@ private void fontSizeChanged(ActionEvent e) { FlatAnimatedLafChange.hideSnapshotWithAnimation(); writeConfigData(); + + + MessageBus.getMessageBus().publishAsync(new FontSizeChangedEvent()); } } diff --git a/src/main/java/mediathek/tool/table/MVTable.java b/src/main/java/mediathek/tool/table/MVTable.java index 973dd086fc..1ffc82cf38 100644 --- a/src/main/java/mediathek/tool/table/MVTable.java +++ b/src/main/java/mediathek/tool/table/MVTable.java @@ -2,6 +2,9 @@ import com.sun.jna.platform.win32.VersionHelpers; import mediathek.config.MVConfig; +import mediathek.gui.messages.FontSizeChangedEvent; +import mediathek.tool.MessageBus; +import net.engio.mbassy.listener.Handler; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; import org.apache.logging.log4j.LogManager; @@ -62,6 +65,14 @@ public MVTable(int maxColumns, boolean @NotNull [] visibleColumStore, calculateRowHeight(); applyWindowsSevenTableEffects(); + + MessageBus.getMessageBus().subscribe(this); + } + + @Handler + private void handleFontSizeChanged(FontSizeChangedEvent e) { + System.out.println("FONT SIZE CHANGED"); + SwingUtilities.invokeLater(this::calculateRowHeight); } /** From 0ee64103e384da99932b075afcabc3859cfcba0d Mon Sep 17 00:00:00 2001 From: Christian F Date: Tue, 8 Aug 2023 13:16:10 +0200 Subject: [PATCH 028/184] - fixes #543 - implement automatic download and quit feature --- CHANGELOG.md | 3 +- src/main/java/mediathek/config/Config.java | 4 ++ .../mediathek/gui/dialog/DialogBeenden.kt | 7 +++- .../mediathek/mainwindow/MediathekGui.java | 39 ++++++++++++++++++- 4 files changed, 50 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13002fcc11..ea868ce7e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,8 @@ - **BUGFIX(Windows/Linux):** Zeilenhöhe der Tabellen wird nun nach Änderung der Schriftart und -größe korrekt justiert. - **FEATURE:** In der Filmliste kann die Darstellung der Info-Icons nun so konfiguriert werden, dass sie links oder Rechts des Titels dargestellt werden. Dies erfolgt mit der Checkbox unter *Einstellungen/Allgemein->Info-Icons der Listen rechts darstellen*. - **FEATURE(Windows/Linux):** Geänderte Programmschriftart und -größe wird nun gespeichert und beim Start wiederhergestellt. -- **FEATURE:** Die URLs des selektierten Films können nun für HQ und normale Auflösung mittels `Strg+Alt+Shift+H` bzw. `Strg+Alt+Shift+N` oder wie bisher über das Kontextmenü in die Zwischenablage kopiert werden. Unter macOS ersetze `Strg` mit `Command`. +- **FEATURE:** Die URLs des selektierten Films können nun für HQ und normale Auflösung mittels `Strg+Alt+Shift+H` bzw. `Strg+Alt+Shift+N` oder wie bisher über das Kontextmenü in die Zwischenablage kopiert werden. Unter macOS ersetze `Strg` mit `Command`. +- **FEATURE:** MV kann mittels `-dq` oder `--download-quit` Parameter zum automatischen Download aller Filme in der Downloadansicht mit anschließender automatischer Beendigung aufgefordert werden. # **14.0.0** - Es wird nun Java 20 verwendet. diff --git a/src/main/java/mediathek/config/Config.java b/src/main/java/mediathek/config/Config.java index b34b55529a..138af64afa 100644 --- a/src/main/java/mediathek/config/Config.java +++ b/src/main/java/mediathek/config/Config.java @@ -66,6 +66,10 @@ public class Config { @CommandLine.Option(names = {"-ns", "--no-splash"}, description = "Splash-Screen nicht anzeigen") private static boolean disableSplashScreen; + @CommandLine.Option(names = {"-dq", "--download-quit"}, description = "Automatisch downloaden, dann beenden") + private static boolean downloadAndQuit; + + public static boolean shouldDownloadAndQuit() { return downloadAndQuit;} public static boolean isSplashScreenDisabled() { return disableSplashScreen;} public static boolean isDisableJvmParameterChecks() { diff --git a/src/main/java/mediathek/gui/dialog/DialogBeenden.kt b/src/main/java/mediathek/gui/dialog/DialogBeenden.kt index b22f3c5de7..be9896f1c3 100644 --- a/src/main/java/mediathek/gui/dialog/DialogBeenden.kt +++ b/src/main/java/mediathek/gui/dialog/DialogBeenden.kt @@ -12,7 +12,7 @@ import java.util.* import java.util.concurrent.TimeUnit import javax.swing.* -class DialogBeenden(parent: JFrame) : JDialog(parent, true) { +class DialogBeenden(parent: JFrame, shouldDownloadAndQuit: Boolean) : JDialog(parent, true) { /** * Indicate whether the application can terminate. */ @@ -220,5 +220,10 @@ class DialogBeenden(parent: JFrame) : JDialog(parent, true) { pack() getRootPane().defaultButton = btnContinue + + if (shouldDownloadAndQuit) { + applicationCanTerminate = true + SwingUtilities.invokeLater { waitUntilDownloadsHaveFinished() } + } } } \ No newline at end of file diff --git a/src/main/java/mediathek/mainwindow/MediathekGui.java b/src/main/java/mediathek/mainwindow/MediathekGui.java index ed2e9f2103..28f60876ba 100644 --- a/src/main/java/mediathek/mainwindow/MediathekGui.java +++ b/src/main/java/mediathek/mainwindow/MediathekGui.java @@ -1,5 +1,7 @@ package mediathek.mainwindow; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; import com.sun.jna.platform.win32.VersionHelpers; import javafx.application.Platform; import javafx.stage.Stage; @@ -226,6 +228,37 @@ public MediathekGui() { logger.trace("Finished loading info dialog"); mapFilmUrlCopyCommands(); + + if (Config.shouldDownloadAndQuit()) { + var future = Daten.getInstance().getDecoratedPool().submit(() -> { + try { + TimeUnit.SECONDS.sleep(10); + logger.info("Auto DL and Quit: Starting all downloads..."); + SwingUtilities.invokeAndWait(() -> tabDownloads.starten(true)); + return true; + + } catch (Exception e) { + logger.error("Auto DL and Quit: error starting downloads", e); + return false; + } + }); + Futures.addCallback(future, new FutureCallback<>() { + @Override + public void onSuccess(Boolean result) { + try { + SwingUtilities.invokeAndWait(() -> quitApplication(true)); + } catch (Exception e) { + logger.error("Auto DL and Quit: Error in callback...", e); + } + } + + @Override + public void onFailure(@NotNull Throwable t) { + + logger.error("Auto DL and Quit: Error in callback...", t); + } + }, Daten.getInstance().getDecoratedPool()); + } } /** @@ -970,9 +1003,13 @@ public void setShutdownRequested(boolean shutdownRequested) { } public boolean quitApplication() { + return quitApplication(false); + } + + public boolean quitApplication(boolean shouldDownloadAndQuit) { if (daten.getListeDownloads().unfinishedDownloads() > 0) { // erst mal prüfen ob noch Downloads laufen - DialogBeenden dialogBeenden = new DialogBeenden(this); + DialogBeenden dialogBeenden = new DialogBeenden(this, shouldDownloadAndQuit); dialogBeenden.setVisible(true); if (!dialogBeenden.getApplicationCanTerminate()) { return false; From 580f1f7da2dcab5b7f34323e1bf594ac478e83d5 Mon Sep 17 00:00:00 2001 From: Christian F Date: Thu, 10 Aug 2023 09:36:27 +0200 Subject: [PATCH 029/184] - cleanup --- .../tool/cellrenderer/CellRendererFilme.java | 43 +++++-------------- 1 file changed, 11 insertions(+), 32 deletions(-) diff --git a/src/main/java/mediathek/tool/cellrenderer/CellRendererFilme.java b/src/main/java/mediathek/tool/cellrenderer/CellRendererFilme.java index 85c5c7754c..ea79dc00ae 100644 --- a/src/main/java/mediathek/tool/cellrenderer/CellRendererFilme.java +++ b/src/main/java/mediathek/tool/cellrenderer/CellRendererFilme.java @@ -104,37 +104,22 @@ public Component getTableCellRendererComponent( //here comes the content... switch (columnModelIndex) { - case DatenFilm.FILM_DAUER: - setText(datenFilm.getFilmLengthAsString()); - break; - - case DatenFilm.FILM_ABSPIELEN: - handleButtonStartColumn(datenDownload, isSelected); - break; - - case DatenFilm.FILM_AUFZEICHNEN: - handleButtonDownloadColumn(isSelected); - break; - - case DatenFilm.FILM_MERKEN: - handleButtonBookmarkColumn(isBookMarked, isSelected, datenFilm.isLivestream()); - break; - - case DatenFilm.FILM_SENDER: + case DatenFilm.FILM_DAUER -> setText(datenFilm.getFilmLengthAsString()); + case DatenFilm.FILM_ABSPIELEN -> handleButtonStartColumn(datenDownload, isSelected); + case DatenFilm.FILM_AUFZEICHNEN -> handleButtonDownloadColumn(isSelected); + case DatenFilm.FILM_MERKEN -> + handleButtonBookmarkColumn(isBookMarked, isSelected, datenFilm.isLivestream()); + case DatenFilm.FILM_SENDER -> { if (mvTable.showSenderIcons()) { Dimension targetDim = getSenderCellDimension(table, row, columnModelIndex); setSenderIcon(value.toString(), targetDim); } - break; - - case DatenFilm.FILM_TITEL: + } + case DatenFilm.FILM_TITEL -> { setText(datenFilm.getTitle()); setIndicatorIcons(table, datenFilm, isSelected); - break; - - case DatenFilm.FILM_GEO: - drawGeolocationIcons(datenFilm, isSelected); - break; + } + case DatenFilm.FILM_GEO -> drawGeolocationIcons(datenFilm, isSelected); } applyColorSettings(this, datenFilm, datenDownload, isSelected, isBookMarked); @@ -199,13 +184,7 @@ private void handleButtonStartColumn(final DatenDownload datenDownload, final bo private void setIconAndToolTip(boolean isSelected, Icon normal, Icon selected, String text) { setToolTipText(text); - Icon icon; - if (isSelected) - icon = selected; - else - icon = normal; - - setIcon(icon); + setIcon(isSelected ? selected : normal); } private void handleButtonDownloadColumn(final boolean isSelected) { From 51de5368d09cad91af625df6c34d54a654d2471d Mon Sep 17 00:00:00 2001 From: Christian F Date: Fri, 11 Aug 2023 12:32:40 +0200 Subject: [PATCH 030/184] - fix link to online help - add links to FAQs --- CHANGELOG.md | 2 + .../java/mediathek/config/Konstanten.java | 4 +- .../gui/actions/ShowOnlineFaqAction.kt | 50 +++++++++++++++++++ .../mediathek/gui/dialog/AboutDialog.java | 34 ++++++++++--- .../java/mediathek/gui/dialog/AboutDialog.jfd | 30 ++++++++--- .../mediathek/mainwindow/MediathekGui.java | 1 + 6 files changed, 107 insertions(+), 14 deletions(-) create mode 100644 src/main/java/mediathek/gui/actions/ShowOnlineFaqAction.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index ea868ce7e3..345833e0c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,12 @@ - **BUGFIX:** Suchfeld wird nach Enter-Taste zum Start der Suche wieder fokussiert. - **BUGFIX:** Programm stürzt nicht mehr ab wenn man versucht während der Indizierung die Blacklist auszuschalten. - **BUGFIX(Windows/Linux):** Zeilenhöhe der Tabellen wird nun nach Änderung der Schriftart und -größe korrekt justiert. +- **BUGFIX:** Link zur Online-Hilfe verweist nurn zur Anleitung, nicht mehr zu den FAQs. - **FEATURE:** In der Filmliste kann die Darstellung der Info-Icons nun so konfiguriert werden, dass sie links oder Rechts des Titels dargestellt werden. Dies erfolgt mit der Checkbox unter *Einstellungen/Allgemein->Info-Icons der Listen rechts darstellen*. - **FEATURE(Windows/Linux):** Geänderte Programmschriftart und -größe wird nun gespeichert und beim Start wiederhergestellt. - **FEATURE:** Die URLs des selektierten Films können nun für HQ und normale Auflösung mittels `Strg+Alt+Shift+H` bzw. `Strg+Alt+Shift+N` oder wie bisher über das Kontextmenü in die Zwischenablage kopiert werden. Unter macOS ersetze `Strg` mit `Command`. - **FEATURE:** MV kann mittels `-dq` oder `--download-quit` Parameter zum automatischen Download aller Filme in der Downloadansicht mit anschließender automatischer Beendigung aufgefordert werden. +- **FEATURE:** Im Hilfe-Menü wurde ein Eintrag zu den Frequently Asked Questions (FAQ) ergänzt. # **14.0.0** - Es wird nun Java 20 verwendet. diff --git a/src/main/java/mediathek/config/Konstanten.java b/src/main/java/mediathek/config/Konstanten.java index 93557a88fe..5bcd471b9b 100644 --- a/src/main/java/mediathek/config/Konstanten.java +++ b/src/main/java/mediathek/config/Konstanten.java @@ -58,8 +58,8 @@ public class Konstanten { public static final String PSET_PROGRAM_GROUP_LIST_PATH = "programmgruppen13/programmgruppen.xml"; public static final String PROGRAM_VERSION_PATH = "prog-info-13.xml"; public static final String ADRESSE_DOWNLOAD = "https://mediathekview.de/download/"; - public static final String ADRESSE_ANLEITUNG = "https://mediathekview.de/anleitung/"; - public static final String ADRESSE_ONLINE_HELP = "https://mediathekview.de/faq/"; + public static final String ADRESSE_ONLINE_HELP = "https://mediathekview.de/anleitung/"; + public static final String ADRESSE_ONLINE_FAQ = "https://mediathekview.de/faq/"; public static final String ADRESSE_WEBSITE = "https://mediathekview.de/"; public static final String ADRESSE_FORUM = "https://forum.mediathekview.de/"; public static final String ADRESSE_DONATION = "https://mediathekview.de/spenden/"; diff --git a/src/main/java/mediathek/gui/actions/ShowOnlineFaqAction.kt b/src/main/java/mediathek/gui/actions/ShowOnlineFaqAction.kt new file mode 100644 index 0000000000..8e6fb460ed --- /dev/null +++ b/src/main/java/mediathek/gui/actions/ShowOnlineFaqAction.kt @@ -0,0 +1,50 @@ +package mediathek.gui.actions + +import mediathek.config.Konstanten +import mediathek.mainwindow.MediathekGui +import mediathek.tool.SVGIconUtilities +import mediathek.tool.SwingErrorDialog +import java.awt.Desktop +import java.awt.event.ActionEvent +import java.io.IOException +import java.net.URI +import java.net.URISyntaxException +import javax.swing.AbstractAction +import javax.swing.JOptionPane + +class ShowOnlineFaqAction(private val ui: MediathekGui) : AbstractAction() { + init { + putValue(NAME, "Frequently Asked Questions (FAQs) anzeigen...") + putValue(SMALL_ICON, SVGIconUtilities.createSVGIcon("icons/fontawesome/circle-question.svg")) + } + + override fun actionPerformed(e: ActionEvent) { + if (Desktop.isDesktopSupported()) { + val d = Desktop.getDesktop() + if (d.isSupported(Desktop.Action.BROWSE)) { + try { + d.browse(URI(Konstanten.ADRESSE_ONLINE_FAQ)) + } catch (ex: IOException) { + SwingErrorDialog.showExceptionMessage( + ui, + "Es trat ein Fehler beim Öffnen der Online-Hilfe auf.\nSollte dies häufiger auftreten kontaktieren Sie bitte das Entwicklerteam.", + ex + ) + } catch (ex: URISyntaxException) { + SwingErrorDialog.showExceptionMessage( + ui, + "Es trat ein Fehler beim Öffnen der Online-Hilfe auf.\nSollte dies häufiger auftreten kontaktieren Sie bitte das Entwicklerteam.", + ex + ) + } + } else { + JOptionPane.showMessageDialog( + ui, + "Ihr Betriebssystem unterstützt das Öffnen des Browsers nicht.
" + + "Bitte öffnen Sie " + Konstanten.ADRESSE_ONLINE_FAQ + " selbst in Ihrem Browser.", + Konstanten.PROGRAMMNAME, JOptionPane.ERROR_MESSAGE + ) + } + } + } +} diff --git a/src/main/java/mediathek/gui/dialog/AboutDialog.java b/src/main/java/mediathek/gui/dialog/AboutDialog.java index a6d7e011e2..80099e088a 100644 --- a/src/main/java/mediathek/gui/dialog/AboutDialog.java +++ b/src/main/java/mediathek/gui/dialog/AboutDialog.java @@ -32,7 +32,8 @@ public AboutDialog(Window owner) { hyperlinkGuiDonation.addActionListener(l -> browseToUrl("https://paypal.me/ChristianFranzke")); hyperlinkServerDonation.addActionListener(l -> browseToUrl(Konstanten.ADRESSE_DONATION)); hyperlinkForum.addActionListener(l -> browseToUrl(Konstanten.ADRESSE_FORUM)); - hyperlinkOnlineHelp.addActionListener(l -> browseToUrl(Konstanten.ADRESSE_ANLEITUNG)); + hyperlinkOnlineHelp.addActionListener(l -> browseToUrl(Konstanten.ADRESSE_ONLINE_HELP)); + hyperlinkFaq.addActionListener(l -> browseToUrl(Konstanten.ADRESSE_ONLINE_FAQ)); hyperlinkJetBrains.addActionListener(l -> browseToUrl("https://www.jetbrains.com")); hyperlinkEjTechnologies.addActionListener(l -> browseToUrl("https://www.ej-technologies.com")); @@ -85,6 +86,8 @@ private void initComponents() { hyperlinkServerDonation = new JXHyperlink(); hyperlinkForum = new JXHyperlink(); hyperlinkOnlineHelp = new JXHyperlink(); + hyperlinkFaq = new JXHyperlink(); + var panel6 = new JPanel(); var label4 = new JLabel(); var panel4 = new JPanel(); hyperlinkJetBrains = new JXHyperlink(); @@ -189,7 +192,8 @@ private void initComponents() { .fill().gap() .fill().gap() .fill().gap() - .fill())); + .fill().gap() + )); //---- hyperlinkHomepage ---- hyperlinkHomepage.setText("Homepage"); //NON-NLS @@ -210,13 +214,30 @@ private void initComponents() { //---- hyperlinkOnlineHelp ---- hyperlinkOnlineHelp.setText("Online-Anleitung"); //NON-NLS panel5.add(hyperlinkOnlineHelp, new CC().cell(0, 4)); + + //---- hyperlinkFaq ---- + hyperlinkFaq.setText("Frequently Asked Questions (FAQ)"); //NON-NLS + panel5.add(hyperlinkFaq, new CC().cell(0, 5)); } contentPane.add(panel5, new CC().cell(0, 1).growX()); - //---- label4 ---- - label4.setText("Die Entwicklung wird unterst\u00fctzt von:"); //NON-NLS - label4.setVerticalAlignment(SwingConstants.TOP); - contentPane.add(label4, new CC().cell(0, 2)); + //======== panel6 ======== + { + panel6.setLayout(new MigLayout( + new LC().fill().insets("0 5 5 5").hideMode(3).gridGap("5", "5"), //NON-NLS + // columns + new AC() + .size("316").fill(), //NON-NLS + // rows + new AC() + .align("top"))); //NON-NLS + + //---- label4 ---- + label4.setText("Die Entwicklung wird unterst\u00fctzt von:"); //NON-NLS + label4.setVerticalAlignment(SwingConstants.TOP); + panel6.add(label4, new CC().cell(0, 0)); + } + contentPane.add(panel6, new CC().cell(0, 2)); //======== panel4 ======== { @@ -254,6 +275,7 @@ private void initComponents() { private JXHyperlink hyperlinkServerDonation; private JXHyperlink hyperlinkForum; private JXHyperlink hyperlinkOnlineHelp; + private JXHyperlink hyperlinkFaq; private JXHyperlink hyperlinkJetBrains; private JXHyperlink hyperlinkEjTechnologies; // JFormDesigner - End of variables declaration //GEN-END:variables diff --git a/src/main/java/mediathek/gui/dialog/AboutDialog.jfd b/src/main/java/mediathek/gui/dialog/AboutDialog.jfd index 45df4c85c1..3326e38ba4 100644 --- a/src/main/java/mediathek/gui/dialog/AboutDialog.jfd +++ b/src/main/java/mediathek/gui/dialog/AboutDialog.jfd @@ -1,4 +1,4 @@ -JFDML JFormDesigner: "7.0.7.0.1134" Java: "11.0.15" encoding: "UTF-8" +JFDML JFormDesigner: "8.1.1.0.298" Java: "17.0.7" encoding: "UTF-8" new FormModel { contentType: "form/swing" @@ -108,7 +108,7 @@ new FormModel { } ) add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$columnConstraints": "[316,fill]" - "$rowConstraints": "[fill][fill][fill][fill][fill]" + "$rowConstraints": "[fill][fill][fill][fill][fill][]" "$layoutConstraints": "fillx,insets 5,hidemode 3,gap 5 5" } ) { name: "panel5" @@ -145,16 +145,34 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 0 4" } ) + add( new FormComponent( "org.jdesktop.swingx.JXHyperlink" ) { + name: "hyperlinkFaq" + "text": "Frequently Asked Questions (FAQ)" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 5" + } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 0 1,growx" } ) - add( new FormComponent( "javax.swing.JLabel" ) { - name: "label4" - "text": "Die Entwicklung wird unterstützt von:" - "verticalAlignment": 1 + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { + "$columnConstraints": "[316,fill]" + "$rowConstraints": "[top]" + "$layoutConstraints": "fill,insets 0 5 5 5,hidemode 3,gap 5 5" + } ) { + name: "panel6" auxiliary() { "JavaCodeGenerator.variableLocal": true } + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label4" + "text": "Die Entwicklung wird unterstützt von:" + "verticalAlignment": 1 + auxiliary() { + "JavaCodeGenerator.variableLocal": true + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 0" + } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 0 2" } ) diff --git a/src/main/java/mediathek/mainwindow/MediathekGui.java b/src/main/java/mediathek/mainwindow/MediathekGui.java index 28f60876ba..9c99d9ecf2 100644 --- a/src/main/java/mediathek/mainwindow/MediathekGui.java +++ b/src/main/java/mediathek/mainwindow/MediathekGui.java @@ -918,6 +918,7 @@ private void handleFilmlistWriteStopEvent(FilmListWriteStopEvent e) { private void createHelpMenu() { jMenuHilfe.add(new ShowOnlineHelpAction()); + jMenuHilfe.add(new ShowOnlineFaqAction(this)); jMenuHilfe.addSeparator(); jMenuHilfe.add(new ResetSettingsAction(this, daten)); jMenuHilfe.add(new ResetDownloadHistoryAction(this)); From b59bea948dd5aeca357c7c9593ba28c1597a62b8 Mon Sep 17 00:00:00 2001 From: Christian F Date: Mon, 14 Aug 2023 18:14:13 +0200 Subject: [PATCH 031/184] - fixes #640 --- src/main/java/mediathek/javafx/filterpanel/FilmActionPanel.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/mediathek/javafx/filterpanel/FilmActionPanel.java b/src/main/java/mediathek/javafx/filterpanel/FilmActionPanel.java index 777c6ed67c..4957c7c205 100644 --- a/src/main/java/mediathek/javafx/filterpanel/FilmActionPanel.java +++ b/src/main/java/mediathek/javafx/filterpanel/FilmActionPanel.java @@ -248,6 +248,8 @@ private FilterDTO renameCurrentFilter(String newValue) { private void setupDeleteFilterButton() { viewSettingsPane.btnDeleteFilterSettings.setOnAction(e -> { + viewSettingsPane.senderCheckList.getCheckModel().clearChecks(); + filterConfig.clearCurrentFilter(); restoreConfigSettings(); }); From a9f92d7f4d4d3c2cd4f269989727fe1701b1f928 Mon Sep 17 00:00:00 2001 From: Christian F Date: Wed, 16 Aug 2023 09:09:48 +0200 Subject: [PATCH 032/184] - add missing doc --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 345833e0c5..67196fe408 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - **BUGFIX:** Programm stürzt nicht mehr ab wenn man versucht während der Indizierung die Blacklist auszuschalten. - **BUGFIX(Windows/Linux):** Zeilenhöhe der Tabellen wird nun nach Änderung der Schriftart und -größe korrekt justiert. - **BUGFIX:** Link zur Online-Hilfe verweist nurn zur Anleitung, nicht mehr zu den FAQs. +- **BUGFIX:** Ein Klick auf das Mülleimer-Icon im Filterdialog setzt nun auch Sender und Thema zurück. - **FEATURE:** In der Filmliste kann die Darstellung der Info-Icons nun so konfiguriert werden, dass sie links oder Rechts des Titels dargestellt werden. Dies erfolgt mit der Checkbox unter *Einstellungen/Allgemein->Info-Icons der Listen rechts darstellen*. - **FEATURE(Windows/Linux):** Geänderte Programmschriftart und -größe wird nun gespeichert und beim Start wiederhergestellt. - **FEATURE:** Die URLs des selektierten Films können nun für HQ und normale Auflösung mittels `Strg+Alt+Shift+H` bzw. `Strg+Alt+Shift+N` oder wie bisher über das Kontextmenü in die Zwischenablage kopiert werden. Unter macOS ersetze `Strg` mit `Command`. From 4abc0b7ab5ca822072aaaa0420f20d690ae59cb0 Mon Sep 17 00:00:00 2001 From: Christian F Date: Sun, 20 Aug 2023 10:19:09 +0200 Subject: [PATCH 033/184] - fix: highlight bookmarked film entries in filmlist again --- CHANGELOG.md | 1 + .../tool/cellrenderer/CellRendererFilme.java | 16 ++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67196fe408..065f864a17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - **BUGFIX(Windows/Linux):** Zeilenhöhe der Tabellen wird nun nach Änderung der Schriftart und -größe korrekt justiert. - **BUGFIX:** Link zur Online-Hilfe verweist nurn zur Anleitung, nicht mehr zu den FAQs. - **BUGFIX:** Ein Klick auf das Mülleimer-Icon im Filterdialog setzt nun auch Sender und Thema zurück. +- **BUGFIX:** Gemerkte Filme werden wieder im Tab Filme farblich hervorgehoben dargestellt. - **FEATURE:** In der Filmliste kann die Darstellung der Info-Icons nun so konfiguriert werden, dass sie links oder Rechts des Titels dargestellt werden. Dies erfolgt mit der Checkbox unter *Einstellungen/Allgemein->Info-Icons der Listen rechts darstellen*. - **FEATURE(Windows/Linux):** Geänderte Programmschriftart und -größe wird nun gespeichert und beim Start wiederhergestellt. - **FEATURE:** Die URLs des selektierten Films können nun für HQ und normale Auflösung mittels `Strg+Alt+Shift+H` bzw. `Strg+Alt+Shift+N` oder wie bisher über das Kontextmenü in die Zwischenablage kopiert werden. Unter macOS ersetze `Strg` mit `Command`. diff --git a/src/main/java/mediathek/tool/cellrenderer/CellRendererFilme.java b/src/main/java/mediathek/tool/cellrenderer/CellRendererFilme.java index ea79dc00ae..a1b0ea0576 100644 --- a/src/main/java/mediathek/tool/cellrenderer/CellRendererFilme.java +++ b/src/main/java/mediathek/tool/cellrenderer/CellRendererFilme.java @@ -152,17 +152,17 @@ private void applyColorSettings(Component c, @NotNull DatenFilm datenFilm, Daten //film is started for download setBackgroundColor(c, datenDownload.start, isSelected); } else { - //not a start, set specific background colors - if (hasBeenSeen) { - if (!isSelected) { + if (!isSelected) { + if (hasBeenSeen) { c.setBackground(MVColor.FILM_HISTORY.color); } - } else if (datenFilm.isNew()) { - // fix #259 - if (!isSelected) + + if (datenFilm.isNew()) { c.setForeground(MVColor.getNewColor()); - } else if (isBookMarked && !isSelected) { - c.setBackground(MVColor.FILM_BOOKMARKED.color); + } + if (isBookMarked) { + c.setBackground(MVColor.FILM_BOOKMARKED.color); + } } } } From 3f2f995e2d1e2eb0c98de6d0ecdd98c43a7e65b7 Mon Sep 17 00:00:00 2001 From: Christian F Date: Sun, 20 Aug 2023 10:23:17 +0200 Subject: [PATCH 034/184] - simplify color application code for film list --- .../tool/cellrenderer/CellRendererFilme.java | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/src/main/java/mediathek/tool/cellrenderer/CellRendererFilme.java b/src/main/java/mediathek/tool/cellrenderer/CellRendererFilme.java index a1b0ea0576..a0bb867400 100644 --- a/src/main/java/mediathek/tool/cellrenderer/CellRendererFilme.java +++ b/src/main/java/mediathek/tool/cellrenderer/CellRendererFilme.java @@ -94,7 +94,7 @@ public Component getTableCellRendererComponent( switch (columnModelIndex) { case DatenFilm.FILM_THEMA, DatenFilm.FILM_TITEL, DatenFilm.FILM_URL -> { var textArea = createTextArea(value.toString()); - applyColorSettings(textArea, datenFilm, datenDownload, isSelected, isBookMarked); + applyColorSettings(textArea, datenFilm, isSelected, isBookMarked); return textArea; } } @@ -122,7 +122,7 @@ public Component getTableCellRendererComponent( case DatenFilm.FILM_GEO -> drawGeolocationIcons(datenFilm, isSelected); } - applyColorSettings(this, datenFilm, datenDownload, isSelected, isBookMarked); + applyColorSettings(this, datenFilm, isSelected, isBookMarked); } catch (Exception ex) { logger.error("Fehler", ex); } @@ -143,26 +143,17 @@ private void applyHorizontalAlignment(final int columnModelIndex) { } } - private void applyColorSettings(Component c, @NotNull DatenFilm datenFilm, DatenDownload datenDownload, boolean isSelected, boolean isBookMarked) { - // gestarteter Film - final boolean start = (datenDownload != null) && (datenDownload.start != null); - final boolean hasBeenSeen = history.hasBeenSeen(datenFilm); - - if (start) { - //film is started for download - setBackgroundColor(c, datenDownload.start, isSelected); - } else { - if (!isSelected) { - if (hasBeenSeen) { - c.setBackground(MVColor.FILM_HISTORY.color); - } + private void applyColorSettings(Component c, @NotNull DatenFilm datenFilm, boolean isSelected, boolean isBookMarked) { + if (!isSelected) { + if (history.hasBeenSeen(datenFilm)) { + c.setBackground(MVColor.FILM_HISTORY.color); + } - if (datenFilm.isNew()) { - c.setForeground(MVColor.getNewColor()); - } - if (isBookMarked) { - c.setBackground(MVColor.FILM_BOOKMARKED.color); - } + if (datenFilm.isNew()) { + c.setForeground(MVColor.getNewColor()); + } + if (isBookMarked) { + c.setBackground(MVColor.FILM_BOOKMARKED.color); } } } From fbf8815da2668259656ea1a873f3cb5c88c0ce70 Mon Sep 17 00:00:00 2001 From: Christian F Date: Sun, 20 Aug 2023 11:14:38 +0200 Subject: [PATCH 035/184] - fix incoherent vertical alignment in tab filme --- CHANGELOG.md | 1 + .../mediathek/tool/cellrenderer/CellRendererFilme.java | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 065f864a17..6baa164661 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - **BUGFIX:** Link zur Online-Hilfe verweist nurn zur Anleitung, nicht mehr zu den FAQs. - **BUGFIX:** Ein Klick auf das Mülleimer-Icon im Filterdialog setzt nun auch Sender und Thema zurück. - **BUGFIX:** Gemerkte Filme werden wieder im Tab Filme farblich hervorgehoben dargestellt. +- **BUGFIX:** Im *Zeilen umbrechen*-Modus des Tab Filme werden die Einträge nun nicht mehr vertikal zentriert. - **FEATURE:** In der Filmliste kann die Darstellung der Info-Icons nun so konfiguriert werden, dass sie links oder Rechts des Titels dargestellt werden. Dies erfolgt mit der Checkbox unter *Einstellungen/Allgemein->Info-Icons der Listen rechts darstellen*. - **FEATURE(Windows/Linux):** Geänderte Programmschriftart und -größe wird nun gespeichert und beim Start wiederhergestellt. - **FEATURE:** Die URLs des selektierten Films können nun für HQ und normale Auflösung mittels `Strg+Alt+Shift+H` bzw. `Strg+Alt+Shift+N` oder wie bisher über das Kontextmenü in die Zwischenablage kopiert werden. Unter macOS ersetze `Strg` mit `Command`. diff --git a/src/main/java/mediathek/tool/cellrenderer/CellRendererFilme.java b/src/main/java/mediathek/tool/cellrenderer/CellRendererFilme.java index a0bb867400..5a064a3cd4 100644 --- a/src/main/java/mediathek/tool/cellrenderer/CellRendererFilme.java +++ b/src/main/java/mediathek/tool/cellrenderer/CellRendererFilme.java @@ -91,6 +91,9 @@ public Component getTableCellRendererComponent( //shortcut if we want to have line breaks, use text areas and skip the rest if (mvTable.isLineBreak()) { + setHorizontalAlignment(SwingConstants.LEFT); + setVerticalAlignment(SwingConstants.TOP); + switch (columnModelIndex) { case DatenFilm.FILM_THEMA, DatenFilm.FILM_TITEL, DatenFilm.FILM_URL -> { var textArea = createTextArea(value.toString()); @@ -99,9 +102,10 @@ public Component getTableCellRendererComponent( } } } + else + applyHorizontalAlignment(columnModelIndex); - applyHorizontalAlignment(columnModelIndex); - + //NOT IN LINEBREAK MODE -> REGULAR HANDLING //here comes the content... switch (columnModelIndex) { case DatenFilm.FILM_DAUER -> setText(datenFilm.getFilmLengthAsString()); From 45bcce51877560b149e0449389b3beebb58c864c Mon Sep 17 00:00:00 2001 From: Christian F Date: Sun, 20 Aug 2023 11:45:38 +0200 Subject: [PATCH 036/184] - fix incoherent vertical alignment in tab downloads --- CHANGELOG.md | 1 + .../cellrenderer/CellRendererDownloads.java | 32 ++++++++++++------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6baa164661..283ea3f27d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - **BUGFIX:** Ein Klick auf das Mülleimer-Icon im Filterdialog setzt nun auch Sender und Thema zurück. - **BUGFIX:** Gemerkte Filme werden wieder im Tab Filme farblich hervorgehoben dargestellt. - **BUGFIX:** Im *Zeilen umbrechen*-Modus des Tab Filme werden die Einträge nun nicht mehr vertikal zentriert. +- **BUGFIX:** Im *Zeilen umbrechen*-Modus des Tab Downloads werden die Einträge nun einheitlich dargestellt. - **FEATURE:** In der Filmliste kann die Darstellung der Info-Icons nun so konfiguriert werden, dass sie links oder Rechts des Titels dargestellt werden. Dies erfolgt mit der Checkbox unter *Einstellungen/Allgemein->Info-Icons der Listen rechts darstellen*. - **FEATURE(Windows/Linux):** Geänderte Programmschriftart und -größe wird nun gespeichert und beim Start wiederhergestellt. - **FEATURE:** Die URLs des selektierten Films können nun für HQ und normale Auflösung mittels `Strg+Alt+Shift+H` bzw. `Strg+Alt+Shift+N` oder wie bisher über das Kontextmenü in die Zwischenablage kopiert werden. Unter macOS ersetze `Strg` mit `Command`. diff --git a/src/main/java/mediathek/tool/cellrenderer/CellRendererDownloads.java b/src/main/java/mediathek/tool/cellrenderer/CellRendererDownloads.java index 9c3669ec95..f7f46e57f5 100644 --- a/src/main/java/mediathek/tool/cellrenderer/CellRendererDownloads.java +++ b/src/main/java/mediathek/tool/cellrenderer/CellRendererDownloads.java @@ -60,6 +60,16 @@ public CellRendererDownloads() { panel.add(progressBar); } + private void applyHorizontalAlignment(int colIndex) { + switch (colIndex) { + case DatenDownload.DOWNLOAD_PROGRESS, DatenDownload.DOWNLOAD_FILM_NR, DatenDownload.DOWNLOAD_NR, DatenDownload.DOWNLOAD_DATUM, DatenDownload.DOWNLOAD_ZEIT, + DatenDownload.DOWNLOAD_DAUER, DatenDownload.DOWNLOAD_BANDBREITE, + DatenDownload.DOWNLOAD_RESTZEIT -> { + setHorizontalAlignment(SwingConstants.CENTER); + } + case DatenDownload.DOWNLOAD_GROESSE -> setHorizontalAlignment(SwingConstants.RIGHT); + } + } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { @@ -70,12 +80,15 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole final int rowModelIndex = table.convertRowIndexToModel(row); final int columnModelIndex = table.convertColumnIndexToModel(column); DatenDownload datenDownload = (DatenDownload) table.getModel().getValueAt(rowModelIndex, DatenDownload.DOWNLOAD_REF); + final MVTable mvTable = (MVTable) table; + + if (mvTable.isLineBreak()) { + setHorizontalAlignment(SwingConstants.LEFT); + setVerticalAlignment(SwingConstants.TOP); - if (((MVTable) table).isLineBreak()) { - JTextArea textArea; switch (columnModelIndex) { case DatenDownload.DOWNLOAD_TITEL, DatenDownload.DOWNLOAD_THEMA, DatenDownload.DOWNLOAD_URL, DatenDownload.DOWNLOAD_PROGRAMM_AUFRUF, DatenDownload.DOWNLOAD_PROGRAMM_AUFRUF_ARRAY, DatenDownload.DOWNLOAD_FILM_URL, DatenDownload.DOWNLOAD_URL_SUBTITLE, DatenDownload.DOWNLOAD_ZIEL_DATEINAME, DatenDownload.DOWNLOAD_ZIEL_PFAD, DatenDownload.DOWNLOAD_ZIEL_PFAD_DATEINAME, DatenDownload.DOWNLOAD_ABO -> { - textArea = new JTextArea(); + var textArea = new JTextArea(); textArea.setLineWrap(true); textArea.setWrapStyleWord(true); textArea.setText(value.toString()); @@ -89,11 +102,12 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole } } } + else + applyHorizontalAlignment(columnModelIndex); switch (columnModelIndex) { case DatenDownload.DOWNLOAD_PROGRESS -> { - setHorizontalAlignment(SwingConstants.CENTER); - if (((MVTable) table).showSenderIcons() && !((MVTable) table).useSmallSenderIcons) { + if (mvTable.showSenderIcons() && !mvTable.useSmallSenderIcons) { progressBar.setBorder(largeBorder); } else { progressBar.setBorder(emptyBorder); @@ -121,7 +135,6 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole if ((int) table.getModel().getValueAt(rowModelIndex, DatenDownload.DOWNLOAD_FILM_NR) == 0) { setText(""); } - setHorizontalAlignment(SwingConstants.CENTER); } case DatenDownload.DOWNLOAD_ART -> { switch (datenDownload.art) { @@ -139,14 +152,9 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole } case DatenDownload.DOWNLOAD_BUTTON_START -> handleButtonStartColumn(datenDownload, isSelected); case DatenDownload.DOWNLOAD_BUTTON_DEL -> handleButtonDeleteColumn(datenDownload, isSelected); - case DatenDownload.DOWNLOAD_GROESSE -> setHorizontalAlignment(SwingConstants.RIGHT); case DatenDownload.DOWNLOAD_ABO -> handleAboColumn(datenDownload); - case DatenDownload.DOWNLOAD_NR, DatenDownload.DOWNLOAD_DATUM, DatenDownload.DOWNLOAD_ZEIT, - DatenDownload.DOWNLOAD_DAUER, DatenDownload.DOWNLOAD_BANDBREITE, - DatenDownload.DOWNLOAD_RESTZEIT -> - setHorizontalAlignment(SwingConstants.CENTER); case DatenDownload.DOWNLOAD_SENDER -> { - if (((MVTable) table).showSenderIcons()) { + if (mvTable.showSenderIcons()) { Dimension targetDim = getSenderCellDimension(table, row, columnModelIndex); setSenderIcon(value.toString(), targetDim); } From 2eae218074e557a7c875317f04054e790327749f Mon Sep 17 00:00:00 2001 From: Christian F Date: Mon, 21 Aug 2023 16:53:19 +0200 Subject: [PATCH 037/184] - reduce the default size area for line break mode --- src/main/java/mediathek/tool/table/MVTable.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/mediathek/tool/table/MVTable.java b/src/main/java/mediathek/tool/table/MVTable.java index 1ffc82cf38..bddbce1d90 100644 --- a/src/main/java/mediathek/tool/table/MVTable.java +++ b/src/main/java/mediathek/tool/table/MVTable.java @@ -138,7 +138,7 @@ private int getSizeArea() { final var height = fm.getHeight(); if (lineBreak) { - sizeArea = 4 * height; + sizeArea = 3 * height; } else { sizeArea = height; From 083c2c84663f715ea907e1746408325bd07803b1 Mon Sep 17 00:00:00 2001 From: Christian F Date: Mon, 21 Aug 2023 16:54:15 +0200 Subject: [PATCH 038/184] - add doc --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 283ea3f27d..f808478318 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - **BUGFIX:** Link zur Online-Hilfe verweist nurn zur Anleitung, nicht mehr zu den FAQs. - **BUGFIX:** Ein Klick auf das Mülleimer-Icon im Filterdialog setzt nun auch Sender und Thema zurück. - **BUGFIX:** Gemerkte Filme werden wieder im Tab Filme farblich hervorgehoben dargestellt. +- **BUGFIX:** Im Zeilenumbruch-Modus sind nun 3 Zeilen Standard statt vorher vier. - **BUGFIX:** Im *Zeilen umbrechen*-Modus des Tab Filme werden die Einträge nun nicht mehr vertikal zentriert. - **BUGFIX:** Im *Zeilen umbrechen*-Modus des Tab Downloads werden die Einträge nun einheitlich dargestellt. - **FEATURE:** In der Filmliste kann die Darstellung der Info-Icons nun so konfiguriert werden, dass sie links oder Rechts des Titels dargestellt werden. Dies erfolgt mit der Checkbox unter *Einstellungen/Allgemein->Info-Icons der Listen rechts darstellen*. From f9877f17f6067b0d7194c69a16adf1dac17b91cc Mon Sep 17 00:00:00 2001 From: Christian F Date: Tue, 22 Aug 2023 15:21:37 +0200 Subject: [PATCH 039/184] - bump xerial jdbc version to fix CVE - use Zulu JDK without JavaFX on non-macOS platforms --- .install4j/mediathekview_linux.install4j | 2 +- .install4j/mediathekview_windows.install4j | 2 +- CHANGELOG.md | 2 ++ pom.xml | 8 +++----- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.install4j/mediathekview_linux.install4j b/.install4j/mediathekview_linux.install4j index 1cef1ad589..1460790635 100644 --- a/.install4j/mediathekview_linux.install4j +++ b/.install4j/mediathekview_linux.install4j @@ -5,7 +5,7 @@ - + diff --git a/.install4j/mediathekview_windows.install4j b/.install4j/mediathekview_windows.install4j index 66611995ca..b481a5c4b1 100644 --- a/.install4j/mediathekview_windows.install4j +++ b/.install4j/mediathekview_windows.install4j @@ -5,7 +5,7 @@ - + diff --git a/CHANGELOG.md b/CHANGELOG.md index f808478318..6d76060059 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ # **14.0.1** +- JDK 20.0.2 wird nun mitgeliefert +- CVE in xerial-jdbc Bibliothek wurde durch eine neuere Version gefixt. - **BUGFIX:** Inkorrekte Beschreibung des "Gespeicherten Film abspielen" Toolbar-Button im Tab Download wurde korrigiert. - **BUGFIX:** Fehlendes Kontextmenü beim Suchfeld wurde hinzugefügt. - **BUGFIX:** Fehlendes Kontextmenü in der Filmbeschreibung zum Kopieren der URL wurde hinzugefügt. diff --git a/pom.xml b/pom.xml index 6b4296ccc6..d129a45a37 100755 --- a/pom.xml +++ b/pom.xml @@ -117,15 +117,13 @@ 4.10.0 5.0.0-alpha.10 4.7.0 - 3.41.2.1 + 3.42.0.0 1.9 mediathek.Main - - 20/jdk-20.0.1+9 - - 20/20.0.1 + + 20/20.0.2 20 From 89b655df320260b7273b378c2a29f7b102ca18f0 Mon Sep 17 00:00:00 2001 From: Christian F Date: Tue, 22 Aug 2023 15:32:35 +0200 Subject: [PATCH 040/184] - remove generation of maven source package jar --- pom.xml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/pom.xml b/pom.xml index d129a45a37..2c4082cc8e 100755 --- a/pom.xml +++ b/pom.xml @@ -515,20 +515,6 @@ maven-surefire-plugin ${maven-surefire-plugin.version} - - org.apache.maven.plugins - maven-source-plugin - ${maven-source-plugin.version} - - - attach-sources - verify - - jar-no-fork - - - - org.jetbrains.kotlin From 1acd546ee495ac6bb974c3705ef2b146287bc322 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Wed, 23 Aug 2023 21:02:32 +0200 Subject: [PATCH 041/184] - fix deprecation warning --- src/main/java/mediathek/tool/Ipify.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/mediathek/tool/Ipify.kt b/src/main/java/mediathek/tool/Ipify.kt index 22114a1507..5c0cd75204 100644 --- a/src/main/java/mediathek/tool/Ipify.kt +++ b/src/main/java/mediathek/tool/Ipify.kt @@ -4,7 +4,6 @@ import java.io.BufferedReader import java.io.IOException import java.io.InputStreamReader import java.net.URI -import java.net.URL import java.net.http.HttpClient import java.net.http.HttpRequest import java.net.http.HttpResponse @@ -20,7 +19,7 @@ object Ipify { @get:Throws(IOException::class) val publicIp: String get() { - val ipify = URL("https://api64.ipify.org") + val ipify = URI("https://api64.ipify.org").toURL() val conn = ipify.openConnection() var ip: String conn.getInputStream().use { inputStream -> From 78fa0d86216612657ca68a1b6c5ae22c6ff78bc2 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Wed, 23 Aug 2023 21:07:46 +0200 Subject: [PATCH 042/184] - implement querying of additional film information via ffprobe - fix deprecation warning for mv_shutdown_helper execution - use new functions for finding binaries on PATH - use current ffmpeg 6 binaries for macOS and windows 64bit --- CHANGELOG.md | 1 + pom.xml | 49 ++++- .../gui/dialog/DialogAddDownload.form | 156 ++++++++++----- .../gui/dialog/DialogAddDownload.java | 188 +++++++++++++----- .../java/mediathek/mac/MediathekGuiMac.kt | 5 +- .../tool/GuiFunktionenProgramme.java | 43 ++++ 6 files changed, 342 insertions(+), 100 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d76060059..31b2d70581 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - **FEATURE:** Die URLs des selektierten Films können nun für HQ und normale Auflösung mittels `Strg+Alt+Shift+H` bzw. `Strg+Alt+Shift+N` oder wie bisher über das Kontextmenü in die Zwischenablage kopiert werden. Unter macOS ersetze `Strg` mit `Command`. - **FEATURE:** MV kann mittels `-dq` oder `--download-quit` Parameter zum automatischen Download aller Filme in der Downloadansicht mit anschließender automatischer Beendigung aufgefordert werden. - **FEATURE:** Im Hilfe-Menü wurde ein Eintrag zu den Frequently Asked Questions (FAQ) ergänzt. +- **FEATURE:** Im *"Film speichern"*-Dialog können nun zur jeweils ausgewählten Qualitätsstufe ergänzende Filminformationen aus dem Netz geladen werden (Höhe x Breite, Bitrate). # **14.0.0** - Es wird nun Java 20 verwendet. diff --git a/pom.xml b/pom.xml index 2c4082cc8e..8b47826cf3 100755 --- a/pom.xml +++ b/pom.xml @@ -97,6 +97,7 @@ 31.1-jre 1.1.2 2.14.1 + 2022.06.03 20.0.1 1.3 5.13.0 @@ -482,6 +483,12 @@ JMacNotification 1.1 + + + com.github.kokorin.jaffree + jaffree + ${jaffree.version} +
@@ -723,7 +730,7 @@ 1.7.0 - download-ffmpeg-exe-from-server + download-ffmpeg-exe-intel-from-server package wget @@ -734,6 +741,18 @@ c075ca784ad26b3ad3f8f49474ee5187 + + download-ffprobe-exe-intel-from-server + package + + wget + + + https://s3.mvorg.de/res/dev/windows/64/bin/ffprobe.exe + ${project.build.directory}/res/bin + 239433c7e3c51021dd678f19d7eaf39e + + @@ -1064,7 +1083,19 @@ https://s3.mvorg.de/res/dev/mac/bin/intel/ffmpeg ${project.build.directory}/bin - 9de5ebaae8f7ad4024a10345ee8d01d5 + 89a30e6e2126216fa3a3339812d14eca + + + + download-intel-ffprobe-from-server + package + + wget + + + https://s3.mvorg.de/res/dev/mac/bin/intel/ffprobe + ${project.build.directory}/bin + 0e2f20dacc9c81e9de742e5eae54637e @@ -1191,7 +1222,19 @@ https://s3.mvorg.de/res/dev/mac/bin/apple_silicon/ffmpeg ${project.build.directory}/bin - 7d60eebebb96059d2d3c3a0599cdefd2 + b286884d4ad306303b30e657606425a0 + + + + download-apple-silicon-ffprobe-from-server + package + + wget + + + https://s3.mvorg.de/res/dev/mac/bin/apple_silicon/ffprobe + ${project.build.directory}/bin + b28d6e1dade2a1773513b86d23c74c13 diff --git a/src/main/java/mediathek/gui/dialog/DialogAddDownload.form b/src/main/java/mediathek/gui/dialog/DialogAddDownload.form index c6b37a97e0..b247004748 100644 --- a/src/main/java/mediathek/gui/dialog/DialogAddDownload.form +++ b/src/main/java/mediathek/gui/dialog/DialogAddDownload.form @@ -35,19 +35,19 @@ - + - + + - @@ -61,14 +61,14 @@ - + - + + - @@ -112,7 +112,7 @@ - + @@ -124,19 +124,9 @@ - - - - - - - - - - - - + + @@ -163,12 +153,7 @@ - - - - - - + @@ -204,7 +189,6 @@ - @@ -219,17 +203,6 @@ - - - - - - - - - - - @@ -245,11 +218,66 @@ - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -266,12 +294,22 @@ - - - - - - + + + + + + + + + + + + + + + + @@ -284,7 +322,12 @@ - + + + + + + @@ -314,6 +357,21 @@ + + + + + + + + + + + + + + + diff --git a/src/main/java/mediathek/gui/dialog/DialogAddDownload.java b/src/main/java/mediathek/gui/dialog/DialogAddDownload.java index 38417caaa1..d58176649e 100644 --- a/src/main/java/mediathek/gui/dialog/DialogAddDownload.java +++ b/src/main/java/mediathek/gui/dialog/DialogAddDownload.java @@ -1,5 +1,8 @@ package mediathek.gui.dialog; +import com.github.kokorin.jaffree.StreamType; +import com.github.kokorin.jaffree.ffprobe.FFprobe; +import com.github.kokorin.jaffree.ffprobe.FFprobeResult; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -68,7 +71,74 @@ public DialogAddDownload(@NotNull Frame parent, @NotNull DatenFilm film, @Nullab setLocationRelativeTo(parent); } + private void setupFilmQualityRadioButtons() { + var listener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + setNameFilm(); + lblFilmInfo.setText(""); + } + }; + jRadioButtonAufloesungHd.addActionListener(listener); + jRadioButtonAufloesungHd.setEnabled(!datenFilm.getHighQualityUrl().isEmpty()); + + jRadioButtonAufloesungKlein.addActionListener(listener); + jRadioButtonAufloesungKlein.setEnabled(!datenFilm.getLowQualityUrl().isEmpty()); + + jRadioButtonAufloesungHoch.addActionListener(listener); + jRadioButtonAufloesungHoch.setSelected(true); + + btnRequestLiveInfo.addActionListener(l -> handleRequestLiveFilmInfo()); + } + + private Path ffprobePath; + + private void handleRequestLiveFilmInfo() { + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + + var res = getFilmResolution(); + var url = datenFilm.getUrlFuerAufloesung(res); + + try { + btnRequestLiveInfo.setEnabled(false); + FFprobeResult result = FFprobe.atPath(ffprobePath) + .setShowStreams(true) + .setInput(url) + .execute(); + + var videoStreamResult = result.getStreams().stream().filter(stream -> stream.getCodecType() == StreamType.VIDEO).findAny(); + videoStreamResult.ifPresentOrElse(stream -> { + var output = String.format("%dx%d, %d kBit/s", stream.getWidth(), stream.getHeight(), stream.getBitRate() / 1000); + lblFilmInfo.setText(output); + + }, () -> lblFilmInfo.setText("Keine Daten verfügbar.")); + btnRequestLiveInfo.setEnabled(true); + } + catch (Exception ex) { + lblFilmInfo.setText("Abrufen der Infos fehlgeschlagen!"); + lblFilmInfo.setForeground(Color.RED); + logger.error("ffprobe execution failed", ex); + } + setCursor(Cursor.getDefaultCursor()); + } + + private void detectFfprobeExecutable() { + try { + ffprobePath = GuiFunktionenProgramme.findExecutableOnPath("ffprobe").getParent(); + } + catch (Exception ex) { + logger.error("ffprobe not found", ex); + lblFilmInfo.setText("Hilfsprogramm nicht gefunden!"); + lblFilmInfo.setForeground(Color.RED); + btnRequestLiveInfo.setEnabled(false); + } + } + private void setupUI() { + lblFilmInfo.setText(""); + + detectFfprobeExecutable(); + // launch async tasks first launchResolutionFutures(); @@ -91,20 +161,7 @@ private void setupUI() { setupNameTextField(); setupPathTextComponent(); - var listener = new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - setNameFilm(); - } - }; - jRadioButtonAufloesungHd.addActionListener(listener); - jRadioButtonAufloesungHd.setEnabled(!datenFilm.getHighQualityUrl().isEmpty()); - - jRadioButtonAufloesungKlein.addActionListener(listener); - jRadioButtonAufloesungKlein.setEnabled(!datenFilm.getLowQualityUrl().isEmpty()); - - jRadioButtonAufloesungHoch.addActionListener(listener); - jRadioButtonAufloesungHoch.setSelected(true); + setupFilmQualityRadioButtons(); setupDeleteHistoryButton(); setupPfadSpeichernCheckBox(); @@ -625,15 +682,18 @@ private void initComponents() { javax.swing.JLabel jLabel4 = new javax.swing.JLabel(); jComboBoxPfad = new javax.swing.JComboBox<>(); jButtonDelHistory = new javax.swing.JButton(); - jCheckBoxPfadSpeichern = new javax.swing.JCheckBox(); - jCheckBoxInfodatei = new javax.swing.JCheckBox(); javax.swing.JLabel jLabelSet = new javax.swing.JLabel(); jComboBoxPset = new javax.swing.JComboBox<>(); + javax.swing.JPanel jPanel2 = new javax.swing.JPanel(); + jCheckBoxInfodatei = new javax.swing.JCheckBox(); + jCheckBoxPfadSpeichern = new javax.swing.JCheckBox(); jCheckBoxSubtitle = new javax.swing.JCheckBox(); jPanelSize = new javax.swing.JPanel(); jRadioButtonAufloesungHd = new javax.swing.JRadioButton(); jRadioButtonAufloesungHoch = new javax.swing.JRadioButton(); jRadioButtonAufloesungKlein = new javax.swing.JRadioButton(); + btnRequestLiveInfo = new javax.swing.JButton(); + lblFilmInfo = new javax.swing.JLabel(); jTextFieldSender = new javax.swing.JTextField(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); @@ -655,20 +715,47 @@ private void initComponents() { jLabel4.setText("Dateiname:"); jComboBoxPfad.setEditable(true); - jComboBoxPfad.setMaximumRowCount(15); jButtonDelHistory.setIcon(new javax.swing.ImageIcon(getClass().getResource("/mediathek/res/muster/button-del.png"))); // NOI18N jButtonDelHistory.setToolTipText("History löschen"); - jCheckBoxPfadSpeichern.setText("Zielpfad speichern"); + jLabelSet.setText("Set:"); jCheckBoxInfodatei.setText("Lege Infodatei an"); jCheckBoxInfodatei.setToolTipText("Erzeugt eine Infodatei im Format \"Infodatei.txt\""); - jLabelSet.setText("Set:"); + jCheckBoxPfadSpeichern.setText("Zielpfad speichern"); jCheckBoxSubtitle.setText("Untertitel speichern: \"Filmname.xxx\""); + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addComponent(jCheckBoxSubtitle) + .addGap(0, 0, Short.MAX_VALUE)) + .addGroup(jPanel2Layout.createSequentialGroup() + .addComponent(jCheckBoxInfodatei) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 295, Short.MAX_VALUE) + .addComponent(jCheckBoxPfadSpeichern))) + .addContainerGap()) + ); + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jCheckBoxPfadSpeichern) + .addComponent(jCheckBoxInfodatei)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jCheckBoxSubtitle) + .addContainerGap()) + ); + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( @@ -683,7 +770,7 @@ private void initComponents() { .addGap(30, 30, 30) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(jComboBoxPfad, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jComboBoxPfad, 0, 374, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButtonZiel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -692,15 +779,8 @@ private void initComponents() { .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(jLabel4) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(jCheckBoxSubtitle) - .addGap(0, 0, Short.MAX_VALUE)) - .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(jCheckBoxInfodatei) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 235, Short.MAX_VALUE) - .addComponent(jCheckBoxPfadSpeichern)) - .addComponent(jTextFieldName)))) + .addComponent(jTextFieldName)) + .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap()) ); jPanel1Layout.setVerticalGroup( @@ -721,11 +801,7 @@ private void initComponents() { .addComponent(jLabel4) .addComponent(jTextFieldName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jCheckBoxPfadSpeichern) - .addComponent(jCheckBoxInfodatei)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(jCheckBoxSubtitle) + .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); @@ -742,18 +818,30 @@ private void initComponents() { buttonGroup1.add(jRadioButtonAufloesungKlein); jRadioButtonAufloesungKlein.setText("Niedrig"); + btnRequestLiveInfo.setText("Filminformationen abrufen..."); + + lblFilmInfo.setFont(lblFilmInfo.getFont().deriveFont(lblFilmInfo.getFont().getSize()-1f)); + lblFilmInfo.setText("jLabel2"); + javax.swing.GroupLayout jPanelSizeLayout = new javax.swing.GroupLayout(jPanelSize); jPanelSize.setLayout(jPanelSizeLayout); jPanelSizeLayout.setHorizontalGroup( jPanelSizeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanelSizeLayout.createSequentialGroup() .addContainerGap() - .addComponent(jRadioButtonAufloesungHd) - .addGap(18, 18, 18) - .addComponent(jRadioButtonAufloesungHoch) - .addGap(18, 18, 18) - .addComponent(jRadioButtonAufloesungKlein) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(jPanelSizeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanelSizeLayout.createSequentialGroup() + .addComponent(jRadioButtonAufloesungHd) + .addGap(18, 18, 18) + .addComponent(jRadioButtonAufloesungHoch) + .addGap(18, 18, 18) + .addComponent(jRadioButtonAufloesungKlein) + .addGap(0, 0, Short.MAX_VALUE)) + .addGroup(jPanelSizeLayout.createSequentialGroup() + .addComponent(btnRequestLiveInfo) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lblFilmInfo, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + .addContainerGap()) ); jPanelSizeLayout.setVerticalGroup( jPanelSizeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -763,7 +851,11 @@ private void initComponents() { .addComponent(jRadioButtonAufloesungHd) .addComponent(jRadioButtonAufloesungHoch) .addComponent(jRadioButtonAufloesungKlein)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 15, Short.MAX_VALUE) + .addGroup(jPanelSizeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnRequestLiveInfo) + .addComponent(lblFilmInfo)) + .addContainerGap()) ); jTextFieldSender.setEditable(false); @@ -780,13 +872,13 @@ private void initComponents() { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jPanelSize, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jTextFieldSender) .addGroup(layout.createSequentialGroup() .addComponent(jCheckBoxStarten) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jButtonOk, javax.swing.GroupLayout.PREFERRED_SIZE, 93, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jButtonAbbrechen)) - .addComponent(jTextFieldSender)) + .addComponent(jButtonAbbrechen))) .addContainerGap()) ); @@ -800,13 +892,13 @@ private void initComponents() { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jPanelSize, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jPanelSize, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jCheckBoxStarten, javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jButtonOk) - .addComponent(jButtonAbbrechen)) - .addComponent(jCheckBoxStarten)) + .addComponent(jButtonAbbrechen))) .addContainerGap()) ); @@ -814,6 +906,7 @@ private void initComponents() { }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnRequestLiveInfo; private javax.swing.JButton jButtonAbbrechen; private javax.swing.JButton jButtonDelHistory; private javax.swing.JButton jButtonOk; @@ -830,5 +923,6 @@ private void initComponents() { private javax.swing.JRadioButton jRadioButtonAufloesungKlein; private javax.swing.JTextField jTextFieldName; private javax.swing.JTextField jTextFieldSender; + private javax.swing.JLabel lblFilmInfo; // End of variables declaration//GEN-END:variables } diff --git a/src/main/java/mediathek/mac/MediathekGuiMac.kt b/src/main/java/mediathek/mac/MediathekGuiMac.kt index a95c3790dc..c87e2d470b 100644 --- a/src/main/java/mediathek/mac/MediathekGuiMac.kt +++ b/src/main/java/mediathek/mac/MediathekGuiMac.kt @@ -6,6 +6,7 @@ import mediathek.gui.messages.DownloadFinishedEvent import mediathek.gui.messages.DownloadStartEvent import mediathek.gui.messages.InstallTabSwitchListenerEvent import mediathek.mainwindow.MediathekGui +import mediathek.tool.GuiFunktionenProgramme import mediathek.tool.notification.INotificationCenter import mediathek.tool.notification.MacNotificationCenter import mediathek.tool.threads.IndicatorThread @@ -18,6 +19,7 @@ import java.awt.desktop.QuitEvent import java.awt.desktop.QuitResponse import java.io.IOException import javax.swing.Box +import kotlin.io.path.absolutePathString class MediathekGuiMac : MediathekGui() { private val powerManager = OsxPowerManager() @@ -48,7 +50,8 @@ class MediathekGuiMac : MediathekGui() { override fun shutdownComputer() { try { - Runtime.getRuntime().exec("nohup bin/mv_shutdown_helper") + val exePath = GuiFunktionenProgramme.findExecutableOnPath("mv_shutdown_helper") + Runtime.getRuntime().exec(arrayOf("nohup", exePath.absolutePathString())) } catch (e: IOException) { logger.error(e) } diff --git a/src/main/java/mediathek/tool/GuiFunktionenProgramme.java b/src/main/java/mediathek/tool/GuiFunktionenProgramme.java index 5f25443bc7..549d265477 100644 --- a/src/main/java/mediathek/tool/GuiFunktionenProgramme.java +++ b/src/main/java/mediathek/tool/GuiFunktionenProgramme.java @@ -19,6 +19,8 @@ import javax.swing.*; import java.awt.*; import java.io.*; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Enumeration; import java.util.zip.ZipEntry; @@ -191,6 +193,47 @@ public static void addSetVorlagen(JFrame parent, Daten daten, ListePset pSet, bo } } + /** + * Return the path to our binary directory. + * @return the path to the bin directory. + */ + public static Path getBinaryPath() { + return Paths.get(GuiFunktionenProgramme.getPathToApplicationJar()).resolve("bin"); + } + + /** + * On Windows exe files can also be located at res\bin... + * @return return the path to res\bin directory. + */ + public static Path getResBinaryPath() { + return Paths.get(GuiFunktionenProgramme.getPathToApplicationJar()).resolve("res").resolve("bin"); + } + + /** + * Search for an executable on PATH plus our bin directory. + * @param name the executable name + * @return the path INCLUDING the binary name. + */ + public static Path findExecutableOnPath(String name) { + var exeString = name; + if (SystemUtils.IS_OS_WINDOWS) + exeString += ".exe"; + + var path = System.getenv("PATH"); + path = path + File.pathSeparatorChar + getBinaryPath().toAbsolutePath(); + // on windows (mostly during coding) binaries do only exist in res\bin directory :( + if (SystemUtils.IS_OS_WINDOWS) + path = path + File.pathSeparatorChar + getResBinaryPath().toAbsolutePath(); + + for (String dirname : path.split(File.pathSeparator)) { + File file = new File(dirname, exeString); + if (file.isFile() /*&& file.canExecute()*/) { + return file.toPath(); + } + } + throw new IllegalStateException(String.format("Should have found the executable %s", exeString)); + } + private static boolean addOnZip(String datei) { String zielPfad = GuiFunktionen.addsPfad(getPathToApplicationJar(), "bin"); File zipFile; From 6f13e79c0c87b2ab163bc660944fb3ec3f890468 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Thu, 24 Aug 2023 09:49:17 +0200 Subject: [PATCH 043/184] - add average framerate - download windows arm ffmpeg binaries --- pom.xml | 33 +++++++++++++++++++ .../gui/dialog/DialogAddDownload.java | 3 +- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8b47826cf3..16ad542586 100755 --- a/pom.xml +++ b/pom.xml @@ -810,6 +810,39 @@ + + org.codehaus.mojo + wagon-maven-plugin + 2.0.2 + + central + + + + http-list + package + + list + + + http://repo1.maven.org/maven2/commons-dbutils/commons-dbutils + + + + + http-download-all + package + + download + + + http://repo1.maven.org/maven2/commons-dbutils/commons-dbutils + ** + ${project.build.directory}/res/bin + + + + org.apache.maven.plugins maven-shade-plugin diff --git a/src/main/java/mediathek/gui/dialog/DialogAddDownload.java b/src/main/java/mediathek/gui/dialog/DialogAddDownload.java index d58176649e..649a4f409c 100644 --- a/src/main/java/mediathek/gui/dialog/DialogAddDownload.java +++ b/src/main/java/mediathek/gui/dialog/DialogAddDownload.java @@ -108,7 +108,8 @@ private void handleRequestLiveFilmInfo() { var videoStreamResult = result.getStreams().stream().filter(stream -> stream.getCodecType() == StreamType.VIDEO).findAny(); videoStreamResult.ifPresentOrElse(stream -> { - var output = String.format("%dx%d, %d kBit/s", stream.getWidth(), stream.getHeight(), stream.getBitRate() / 1000); + var fr = stream.getAvgFrameRate().intValue(); + var output = String.format("%dx%d, %d kBit/s, %d fps (avg)", stream.getWidth(), stream.getHeight(), stream.getBitRate() / 1000, fr); lblFilmInfo.setText(output); }, () -> lblFilmInfo.setText("Keine Daten verfügbar.")); From 89a80237b53acc841c8368cf4e1996466f02f014 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Thu, 24 Aug 2023 10:04:19 +0200 Subject: [PATCH 044/184] - attempt to fix download aarch64 win --- pom.xml | 49 ++++++++++++++++++------------------------------- 1 file changed, 18 insertions(+), 31 deletions(-) diff --git a/pom.xml b/pom.xml index 16ad542586..e15a533973 100755 --- a/pom.xml +++ b/pom.xml @@ -811,37 +811,24 @@ - org.codehaus.mojo - wagon-maven-plugin - 2.0.2 - - central - - - - http-list - package - - list - - - http://repo1.maven.org/maven2/commons-dbutils/commons-dbutils - - - - - http-download-all - package - - download - - - http://repo1.maven.org/maven2/commons-dbutils/commons-dbutils - ** - ${project.build.directory}/res/bin - - - + com.googlecode.maven-download-plugin + download-maven-plugin + 1.7.0 + + + download-ffmpeg-exe-aarch64-from-server + package + + wget + + + https://s3.mvorg.de/res/dev/windows/aarch64/ffmpeg.zip + true + ${project.build.directory}/res/bin + f5429db43834da7e58c88fd7baa05ce8 + + + org.apache.maven.plugins From 4bdc6d217a8b02509da2ef7116d952f48ac741c4 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Thu, 24 Aug 2023 14:46:50 +0200 Subject: [PATCH 045/184] - remove deprecated code --- src/main/java/mediathek/tool/Ipify.kt | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/main/java/mediathek/tool/Ipify.kt b/src/main/java/mediathek/tool/Ipify.kt index 5c0cd75204..8d0dc5e134 100644 --- a/src/main/java/mediathek/tool/Ipify.kt +++ b/src/main/java/mediathek/tool/Ipify.kt @@ -1,8 +1,6 @@ package mediathek.tool -import java.io.BufferedReader import java.io.IOException -import java.io.InputStreamReader import java.net.URI import java.net.http.HttpClient import java.net.http.HttpRequest @@ -18,23 +16,6 @@ object Ipify { @JvmStatic @get:Throws(IOException::class) val publicIp: String - get() { - val ipify = URI("https://api64.ipify.org").toURL() - val conn = ipify.openConnection() - var ip: String - conn.getInputStream().use { inputStream -> - InputStreamReader(inputStream).use { isr -> - BufferedReader(isr).use { reader -> - ip = reader.readLine() - } - } - } - return ip - } - - @JvmStatic - @get:Throws(IOException::class) - val publicIpNew: String get() { val client: HttpClient = HttpClient.newBuilder() .version(HttpClient.Version.HTTP_2) From fb5c5f8412c0daf86564dabc874d5bd753d6ee40 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Mon, 28 Aug 2023 12:21:08 +0200 Subject: [PATCH 046/184] - change deprecated code - remove old incomplete CDN detection code - remove sender download limit --- .../java/mediathek/daten/ListeDownloads.java | 98 ++----------------- 1 file changed, 9 insertions(+), 89 deletions(-) diff --git a/src/main/java/mediathek/daten/ListeDownloads.java b/src/main/java/mediathek/daten/ListeDownloads.java index 6aff44927a..c2739f63e9 100644 --- a/src/main/java/mediathek/daten/ListeDownloads.java +++ b/src/main/java/mediathek/daten/ListeDownloads.java @@ -36,12 +36,13 @@ import org.apache.logging.log4j.Logger; import javax.swing.*; -import java.net.URL; -import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; public class ListeDownloads extends LinkedList { + private static final Logger logger = LogManager.getLogger(ListeDownloads.class); private final Daten daten; public ListeDownloads(Daten daten_) { @@ -53,8 +54,6 @@ public synchronized void addMitNummer(DatenDownload e) { listeNummerieren(); } - private static final Logger logger = LogManager.getLogger(ListeDownloads.class); - public synchronized void filmEintragen() { // bei einmal Downloads nach einem Programmstart/Neuladen der Filmliste // den Film wieder eintragen @@ -140,6 +139,7 @@ public synchronized void abosAuffrischen() { /** * Get the number of unfinished download tasks. + * * @return number of unfinished tasks */ public synchronized long unfinishedDownloads() { @@ -347,8 +347,7 @@ public synchronized void abosSuchen(JFrame parent) { // prüfen ob in "alle Filme" oder nur "nach Blacklist" gesucht werden soll boolean checkWithBlackList = Boolean.parseBoolean(MVConfig.get(MVConfig.Configs.SYSTEM_BLACKLIST_AUCH_ABO)); DatenPset pSet_ = Daten.listePset.getPsetAbo(""); - final var sdf = new SimpleDateFormat("dd.MM.yyyy"); - final var todayDateStr = sdf.format(new Date()); + var todayDateStr = DateTimeFormatter.ofPattern("dd.MM.yyyy").format(LocalDateTime.now()); final var listeAbo = daten.getListeAbo(); final var listeBlacklist = daten.getListeBlacklist(); @@ -483,7 +482,7 @@ public synchronized DatenDownload getNextStart() { // und versuchen dass bei mehreren laufenden Downloads ein anderer Sender gesucht wird final DatenDownload[] ret = new DatenDownload[1]; - final int maxNumDownloads = ApplicationConfiguration.getConfiguration().getInt(ApplicationConfiguration.DOWNLOAD_MAX_SIMULTANEOUS_NUM,1); + final int maxNumDownloads = ApplicationConfiguration.getConfiguration().getInt(ApplicationConfiguration.DOWNLOAD_MAX_SIMULTANEOUS_NUM, 1); if (this.size() > 0 && getDown(maxNumDownloads)) { nextPossibleDownload().ifPresent(datenDownload -> { if (datenDownload.start != null) { @@ -508,10 +507,9 @@ public DatenDownload getRestartDownload() { } if (datenDownload.start.status == Start.STATUS_ERR - && datenDownload.start.countRestarted < Konstanten.MAX_DOWNLOAD_RESTARTS - && !maxSenderLaufen(datenDownload, 1)) { + && datenDownload.start.countRestarted < Konstanten.MAX_DOWNLOAD_RESTARTS) { int restarted = datenDownload.start.countRestarted; - if ( /*datenDownload.art == DatenDownload.ART_PROGRAMM && datenDownload.isRestart() || */datenDownload.art == DatenDownload.ART_DOWNLOAD) { + if (datenDownload.art == DatenDownload.ART_DOWNLOAD) { datenDownload.resetDownload(); datenDownload.startDownload(); datenDownload.start.countRestarted = ++restarted; //datenDownload.start ist neu!!! @@ -539,92 +537,14 @@ private boolean getDown(int max) { } private Optional nextPossibleDownload() { - //erster Versuch, Start mit einem anderen Sender - for (DatenDownload datenDownload : this) { - if (datenDownload.start != null) { - if (datenDownload.start.status == Start.STATUS_INIT) { - if (!maxSenderLaufen(datenDownload, 1)) { - return Optional.of(datenDownload); - } - } - } - } - - //zweiter Versuch, Start mit einem passenden Sender for (DatenDownload datenDownload : this) { if (datenDownload.start != null) { if (datenDownload.start.status == Start.STATUS_INIT) { - if (!maxSenderLaufen(datenDownload, Konstanten.MAX_SENDER_FILME_LADEN)) { - return Optional.of(datenDownload); - } + return Optional.of(datenDownload); } } } return Optional.empty(); } - - /** - * Check if host is part of a CDN server network. - * Currently we only check for Akamai - * @param host url - * @return true if it belongs to a CDN - */ - private boolean isCDN(final String host) { - return host.contains("akamaihd.net") || host.contains("cdn-storage.br.de"); - } - - private boolean maxSenderLaufen(DatenDownload d, final int max) { - //true wenn bereits die maxAnzahl pro Sender läuft - try { - int counter = 0; - final String host = getHost(d); - for (DatenDownload download : this) { - if (download.start != null) { - if (download.start.status == Start.STATUS_RUN - && getHost(download).equalsIgnoreCase(host)) { - if (!isCDN(d.arr[DatenDownload.DOWNLOAD_FILM_URL])) { - counter++; - if (counter >= max) { - return true; - } - } - } - } - } - return false; - } catch (Exception ex) { - return false; - } - } - - private String getHost(DatenDownload datenDownload) { - String host = ""; - try { - try { - URL url = new URL(datenDownload.arr[DatenDownload.DOWNLOAD_URL]); - String tmp = url.getHost(); - if (tmp.contains(".")) { - host = tmp.substring(tmp.lastIndexOf('.')); - tmp = tmp.substring(0, tmp.lastIndexOf('.')); - if (tmp.contains(".")) { - host = tmp.substring(tmp.lastIndexOf('.') + 1) + host; - } else if (tmp.contains("/")) { - host = tmp.substring(tmp.lastIndexOf('/') + 1) + host; - } else { - host = "host"; - } - } - } catch (Exception ex) { - host = "host"; - } finally { - if (host.isEmpty()) { - host = "host"; - } - } - } catch (Exception ex) { - host = "exception"; - } - return host; - } } From e7e98a3d7d2ff98ea96fc8d0f3130fa5187ede36 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Mon, 28 Aug 2023 12:23:34 +0200 Subject: [PATCH 047/184] - fix deprecation warning --- src/test/kotlin/feed/RSSFeedParserTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/kotlin/feed/RSSFeedParserTest.kt b/src/test/kotlin/feed/RSSFeedParserTest.kt index f7c59d7386..6f281366b1 100644 --- a/src/test/kotlin/feed/RSSFeedParserTest.kt +++ b/src/test/kotlin/feed/RSSFeedParserTest.kt @@ -2,13 +2,13 @@ package feed import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test -import java.net.URL +import java.net.URI internal class RSSFeedParserTest { @Test fun mvwTest() { try { - URL("https://mediathekviewweb.de/feed").openStream().use { + URI("https://mediathekviewweb.de/feed").toURL().openStream().use { val parser = RSSFeedParser() val feed = parser.readFeed(it) Assertions.assertNotNull(feed) From da4d79b0387e4964ac50e37f32ba6330b01cc66a Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Mon, 28 Aug 2023 12:24:30 +0200 Subject: [PATCH 048/184] - fix javadoc warning --- src/main/java/mediathek/tool/DarkModeDetector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/mediathek/tool/DarkModeDetector.java b/src/main/java/mediathek/tool/DarkModeDetector.java index eb8979cb5f..bb42c6bbb0 100644 --- a/src/main/java/mediathek/tool/DarkModeDetector.java +++ b/src/main/java/mediathek/tool/DarkModeDetector.java @@ -11,7 +11,7 @@ /** * Dark mode detector for macOS and Windows. - * Based on java code from https://gist.github.com/HanSolo/7cf10b86efff8ca2845bf5ec2dd0fe1d + * Based on java code from this gist. */ public class DarkModeDetector { public static final Map MACOS_ACCENT_COLOR_MAP = Map.of(-1, new Color[] { MacOSSystemColor.GRAY.colorAqua, MacOSSystemColor.GRAY.colorDark }, From fc39af06c2fcad799507f460f690ed3dbbae76c8 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Mon, 28 Aug 2023 14:22:51 +0200 Subject: [PATCH 049/184] - fix deprecation warnings --- src/main/java/mediathek/controller/starter/RuntimeExec.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/mediathek/controller/starter/RuntimeExec.java b/src/main/java/mediathek/controller/starter/RuntimeExec.java index 38968031f4..d311def503 100644 --- a/src/main/java/mediathek/controller/starter/RuntimeExec.java +++ b/src/main/java/mediathek/controller/starter/RuntimeExec.java @@ -106,8 +106,8 @@ public Process exec(boolean log) { Thread clearIn = new Thread(new ClearInOut(IoType.INPUT, process)); Thread clearOut = new Thread(new ClearInOut(IoType.ERROR, process)); - clearIn.setName("ClearIn: " + clearIn.getId()); - clearOut.setName("ClearOut: " + clearOut.getId()); + clearIn.setName("ClearIn: " + clearIn.threadId()); + clearOut.setName("ClearOut: " + clearOut.threadId()); clearIn.start(); clearOut.start(); } catch (Exception ex) { @@ -124,7 +124,7 @@ private enum IoType {INPUT, ERROR} static class PatternCacheLoader extends CacheLoader { @Override - public Pattern load(@NotNull String pattern) throws IllegalArgumentException { + public @NotNull Pattern load(@NotNull String pattern) throws IllegalArgumentException { logger.trace("COMPILING RuntimeExec PATTERN: " + pattern); return Pattern.compile(pattern); } From 475a95b9f02f43547ee0e3a6df7db568c5230c52 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Mon, 28 Aug 2023 14:31:13 +0200 Subject: [PATCH 050/184] - fix lucene deprecation warning --- .../gui/tabs/tab_film/helpers/LuceneGuiFilmeModelHelper.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/mediathek/gui/tabs/tab_film/helpers/LuceneGuiFilmeModelHelper.java b/src/main/java/mediathek/gui/tabs/tab_film/helpers/LuceneGuiFilmeModelHelper.java index 04b64b23c7..a82e24612f 100644 --- a/src/main/java/mediathek/gui/tabs/tab_film/helpers/LuceneGuiFilmeModelHelper.java +++ b/src/main/java/mediathek/gui/tabs/tab_film/helpers/LuceneGuiFilmeModelHelper.java @@ -164,8 +164,8 @@ private TModelFilm performTableFiltering() { Set filmNrSet = new HashSet<>(hits.length); for (var hit : hits) { - var d = searcher.doc(hit.doc); - filmNrSet.add(Integer.parseInt(d.get(LuceneIndexKeys.ID))); + final var id = searcher.storedFields().document(hit.doc).get(LuceneIndexKeys.ID); + filmNrSet.add(Integer.parseInt(id)); } logger.trace("Number of found Lucene index entries: {}", filmNrSet.size()); stream = listeFilme.parallelStream() From f23ea342685f264c7b75f538cc3d2df5f60dbbe0 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Mon, 28 Aug 2023 14:47:35 +0200 Subject: [PATCH 051/184] - fix deprecation warning --- src/main/java/mediathek/windows/MediathekGuiWindows.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/mediathek/windows/MediathekGuiWindows.java b/src/main/java/mediathek/windows/MediathekGuiWindows.java index 4a0743097b..4c07b0b293 100644 --- a/src/main/java/mediathek/windows/MediathekGuiWindows.java +++ b/src/main/java/mediathek/windows/MediathekGuiWindows.java @@ -9,7 +9,6 @@ import java.io.IOException; -@SuppressWarnings("serial") public class MediathekGuiWindows extends MediathekGui { private final Logger logger = LogManager.getLogger(MediathekGuiWindows.class); public MediathekGuiWindows() { @@ -18,10 +17,10 @@ public MediathekGuiWindows() { @Override protected void shutdownComputer() { - final String strShutdownCommand = "shutdown.exe -s -t 0"; + final String[] strShutdownCommand = {"shutdown.exe", "-s", "-t", "0"}; try { - logger.info("Shutdown: {}", strShutdownCommand); + logger.info("Windows shutdown binary called."); Runtime.getRuntime().exec(strShutdownCommand); } catch (IOException ex) { logger.error(ex); From df2f22dbdec10676ad3a4bae06af58fd5a1cb3b4 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Mon, 28 Aug 2023 17:47:05 +0200 Subject: [PATCH 052/184] - code rename --- src/main/java/mediathek/tool/http/MVHttpClient.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/mediathek/tool/http/MVHttpClient.java b/src/main/java/mediathek/tool/http/MVHttpClient.java index 099c587265..f0cd98a008 100644 --- a/src/main/java/mediathek/tool/http/MVHttpClient.java +++ b/src/main/java/mediathek/tool/http/MVHttpClient.java @@ -26,7 +26,7 @@ public class MVHttpClient { private final Configuration config = ApplicationConfiguration.getConfiguration(); private final ByteCounter byteCounter = new ByteCounter(); private OkHttpClient httpClient; - private OkHttpClient copyClient; + private OkHttpClient reducedTimeoutClient; private MVHttpClient() { String proxyHost = System.getProperty("http.proxyHost"); @@ -163,7 +163,7 @@ private void setupProxyClients(Proxy proxy) { if (proxyAuthenticator != null) tmpBuilder.proxyAuthenticator(proxyAuthenticator); - copyClient = tmpBuilder.build(); + reducedTimeoutClient = tmpBuilder.build(); } /** @@ -173,7 +173,7 @@ private void setupNonProxyClients() { httpClient = getDefaultClientBuilder() .build(); - copyClient = getDefaultClientBuilder() + reducedTimeoutClient = getDefaultClientBuilder() .connectTimeout(5, TimeUnit.SECONDS) .readTimeout(5, TimeUnit.SECONDS) .writeTimeout(2, TimeUnit.SECONDS) @@ -187,6 +187,6 @@ public OkHttpClient getHttpClient() { } public OkHttpClient getReducedTimeOutClient() { - return copyClient; + return reducedTimeoutClient; } } From 91d408d904b9224b67d187180cb4f368699b875a Mon Sep 17 00:00:00 2001 From: Sebastian Wiesner Date: Sun, 27 Aug 2023 11:02:56 +0200 Subject: [PATCH 053/184] Use non-deprecated .exec overload --- src/main/java/mediathek/tool/DarkModeDetector.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/mediathek/tool/DarkModeDetector.java b/src/main/java/mediathek/tool/DarkModeDetector.java index bb42c6bbb0..dbcdd2a309 100644 --- a/src/main/java/mediathek/tool/DarkModeDetector.java +++ b/src/main/java/mediathek/tool/DarkModeDetector.java @@ -55,7 +55,7 @@ private static boolean isMacOsDarkMode() { try { boolean isDarkMode = false; - var process = Runtime.getRuntime().exec("defaults read -g AppleInterfaceStyle"); + var process = Runtime.getRuntime().exec(new String[]{"defaults", "read", "-g", "AppleInterfaceStyle"}); isr = new InputStreamReader(process.getInputStream()); rdr = new BufferedReader(isr); String line; @@ -110,7 +110,7 @@ public static Color getMacOSAccentColor() { try { Integer colorKey = null; Runtime runtime = Runtime.getRuntime(); - Process process = runtime.exec("defaults read -g AppleAccentColor"); + Process process = runtime.exec(new String[]{"defaults", "read", "-g", "AppleAccentColor"}); InputStreamReader isr = new InputStreamReader(process.getInputStream()); BufferedReader rdr = new BufferedReader(isr); String line; From a00a0531fe0a0c605544ac19e64c9417da1fd607 Mon Sep 17 00:00:00 2001 From: Sebastian Wiesner Date: Sun, 27 Aug 2023 11:10:18 +0200 Subject: [PATCH 054/184] Detect Gnome dark mode --- .../java/mediathek/tool/DarkModeDetector.java | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/main/java/mediathek/tool/DarkModeDetector.java b/src/main/java/mediathek/tool/DarkModeDetector.java index dbcdd2a309..b4c50a4210 100644 --- a/src/main/java/mediathek/tool/DarkModeDetector.java +++ b/src/main/java/mediathek/tool/DarkModeDetector.java @@ -7,6 +7,7 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; /** @@ -37,16 +38,38 @@ public static boolean isDarkMode() { return isMacOsDarkMode(); else if (SystemUtils.IS_OS_WINDOWS) return isWindowsDarkMode(); + else if (SystemUtils.IS_OS_LINUX && isGnome()) + return isGnomeDarkMode(); else return false; } + private static boolean isGnome() { + var currentDesktop = System.getenv("XDG_CURRENT_DESKTOP"); + return currentDesktop != null && currentDesktop.equals("GNOME"); + } + /** * Indicate if dark mode detection is supported on the current platform. * @return true if supported, false otherwise. */ public static boolean hasDarkModeDetectionSupport() { - return SystemUtils.IS_OS_WINDOWS || SystemUtils.IS_OS_MAC_OSX; + return SystemUtils.IS_OS_WINDOWS || SystemUtils.IS_OS_MAC_OSX || + (SystemUtils.IS_OS_LINUX && isGnome()); + } + + private static boolean isGnomeDarkMode() { + try { + var process = Runtime.getRuntime().exec(new String[]{"gsettings", "get", "org.gnome.desktop.interface", "color-scheme"}); + var buffer = new StringWriter(); + try (var source = new InputStreamReader(process.getInputStream())) { + source.transferTo(buffer); + } + var rc = process.waitFor(5, TimeUnit.SECONDS); + return rc && buffer.toString().trim().equals( "'prefer-dark'"); + } catch (IOException | InterruptedException e) { + return false; + } } private static boolean isMacOsDarkMode() { From 408dc8927b906c39c245dc41c25ad3fb4b86cb9c Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Mon, 28 Aug 2023 17:47:05 +0200 Subject: [PATCH 055/184] - code rename --- src/main/java/mediathek/tool/http/MVHttpClient.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/mediathek/tool/http/MVHttpClient.java b/src/main/java/mediathek/tool/http/MVHttpClient.java index 099c587265..f0cd98a008 100644 --- a/src/main/java/mediathek/tool/http/MVHttpClient.java +++ b/src/main/java/mediathek/tool/http/MVHttpClient.java @@ -26,7 +26,7 @@ public class MVHttpClient { private final Configuration config = ApplicationConfiguration.getConfiguration(); private final ByteCounter byteCounter = new ByteCounter(); private OkHttpClient httpClient; - private OkHttpClient copyClient; + private OkHttpClient reducedTimeoutClient; private MVHttpClient() { String proxyHost = System.getProperty("http.proxyHost"); @@ -163,7 +163,7 @@ private void setupProxyClients(Proxy proxy) { if (proxyAuthenticator != null) tmpBuilder.proxyAuthenticator(proxyAuthenticator); - copyClient = tmpBuilder.build(); + reducedTimeoutClient = tmpBuilder.build(); } /** @@ -173,7 +173,7 @@ private void setupNonProxyClients() { httpClient = getDefaultClientBuilder() .build(); - copyClient = getDefaultClientBuilder() + reducedTimeoutClient = getDefaultClientBuilder() .connectTimeout(5, TimeUnit.SECONDS) .readTimeout(5, TimeUnit.SECONDS) .writeTimeout(2, TimeUnit.SECONDS) @@ -187,6 +187,6 @@ public OkHttpClient getHttpClient() { } public OkHttpClient getReducedTimeOutClient() { - return copyClient; + return reducedTimeoutClient; } } From 80a6f7b1a1a1dcf105f6ce8ebb45ebeff2e6768d Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Tue, 29 Aug 2023 19:08:04 +0200 Subject: [PATCH 056/184] - document linux GNOME dark mode detection PR --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31b2d70581..2c8b46cd21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - **FEATURE:** MV kann mittels `-dq` oder `--download-quit` Parameter zum automatischen Download aller Filme in der Downloadansicht mit anschließender automatischer Beendigung aufgefordert werden. - **FEATURE:** Im Hilfe-Menü wurde ein Eintrag zu den Frequently Asked Questions (FAQ) ergänzt. - **FEATURE:** Im *"Film speichern"*-Dialog können nun zur jeweils ausgewählten Qualitätsstufe ergänzende Filminformationen aus dem Netz geladen werden (Höhe x Breite, Bitrate). +- **FEATURE(Linux):** Dark Mode Erkennung funktioniert nun auch mit GNOME. Danke an @swsnr! # **14.0.0** - Es wird nun Java 20 verwendet. From 5594a135426747436f100d0c5f8e2344a35dc4b8 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Tue, 29 Aug 2023 19:29:52 +0200 Subject: [PATCH 057/184] - detect GNOME on Ubuntu --- src/main/java/mediathek/tool/DarkModeDetector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/mediathek/tool/DarkModeDetector.java b/src/main/java/mediathek/tool/DarkModeDetector.java index b4c50a4210..bf41eb40cd 100644 --- a/src/main/java/mediathek/tool/DarkModeDetector.java +++ b/src/main/java/mediathek/tool/DarkModeDetector.java @@ -46,7 +46,7 @@ else if (SystemUtils.IS_OS_LINUX && isGnome()) private static boolean isGnome() { var currentDesktop = System.getenv("XDG_CURRENT_DESKTOP"); - return currentDesktop != null && currentDesktop.equals("GNOME"); + return currentDesktop != null && (currentDesktop.equals("GNOME") || currentDesktop.equals("ubuntu:GNOME")); } /** From 8cc73324767fb005e3f5ebca75fa1a965fc4f18e Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Wed, 30 Aug 2023 14:52:05 +0200 Subject: [PATCH 058/184] - fix EDT violation --- src/main/java/mediathek/filmlisten/FilmeLaden.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/mediathek/filmlisten/FilmeLaden.java b/src/main/java/mediathek/filmlisten/FilmeLaden.java index 812e5328a2..5fce416947 100644 --- a/src/main/java/mediathek/filmlisten/FilmeLaden.java +++ b/src/main/java/mediathek/filmlisten/FilmeLaden.java @@ -278,10 +278,10 @@ private void undEnde(ListenerFilmeLadenEvent event) { if (event.fehler) { logger.info(""); logger.info("Filmliste laden war fehlerhaft, alte Liste wird wieder geladen"); - JOptionPane.showMessageDialog(MediathekGui.ui(), + SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(MediathekGui.ui(), "Das Laden der Filmliste hat nicht geklappt!", Konstanten.PROGRAMMNAME, - JOptionPane.ERROR_MESSAGE); + JOptionPane.ERROR_MESSAGE)); // dann die alte Liste wieder laden listeFilme.clear(); From dabeaa2530bc16c8459f7cca122ed85229f4ea55 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Wed, 30 Aug 2023 17:41:00 +0200 Subject: [PATCH 059/184] - enable window decorations on linux --- src/main/java/mediathek/Main.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/mediathek/Main.java b/src/main/java/mediathek/Main.java index 3dfe146877..3ca353dc67 100644 --- a/src/main/java/mediathek/Main.java +++ b/src/main/java/mediathek/Main.java @@ -392,8 +392,12 @@ public static void main(final String... args) { setupDockIcon(); setupFlatLaf(); - if (SystemUtils.IS_OS_LINUX) + if (SystemUtils.IS_OS_LINUX) { checkUiScaleSetting(); + // enable custom window decorations + JFrame.setDefaultLookAndFeelDecorated( true ); + JDialog.setDefaultLookAndFeelDecorated( true ); + } if (!Config.isDisableJvmParameterChecks()) checkJVMSettings(); From 38032eef0b16a552aeb67c8fbc8bee380f0662c4 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Wed, 30 Aug 2023 17:44:35 +0200 Subject: [PATCH 060/184] - add missing doc decorations --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c8b46cd21..f564c6d6cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ - **FEATURE:** Im Hilfe-Menü wurde ein Eintrag zu den Frequently Asked Questions (FAQ) ergänzt. - **FEATURE:** Im *"Film speichern"*-Dialog können nun zur jeweils ausgewählten Qualitätsstufe ergänzende Filminformationen aus dem Netz geladen werden (Höhe x Breite, Bitrate). - **FEATURE(Linux):** Dark Mode Erkennung funktioniert nun auch mit GNOME. Danke an @swsnr! - +- **FEATURE(Linux):** Die Fensterdekorationen der Windows/macOS-Versionen werden nun auch unter Linux verwendet. # **14.0.0** - Es wird nun Java 20 verwendet. - User Interface wurde primär für neue macOS-Versionen überarbeitet. From 558038067f8e57f7dd7a129d21950d8da1ac514f Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Wed, 30 Aug 2023 17:46:24 +0200 Subject: [PATCH 061/184] - linux decorations were installed too late --- src/main/java/mediathek/Main.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/mediathek/Main.java b/src/main/java/mediathek/Main.java index 3ca353dc67..0a520832c4 100644 --- a/src/main/java/mediathek/Main.java +++ b/src/main/java/mediathek/Main.java @@ -389,14 +389,17 @@ public static void main(final String... args) { setupLogging(); printPortableModeInfo(); + if (SystemUtils.IS_OS_LINUX) { + // enable custom window decorations + JFrame.setDefaultLookAndFeelDecorated( true ); + JDialog.setDefaultLookAndFeelDecorated( true ); + } + setupDockIcon(); setupFlatLaf(); if (SystemUtils.IS_OS_LINUX) { checkUiScaleSetting(); - // enable custom window decorations - JFrame.setDefaultLookAndFeelDecorated( true ); - JDialog.setDefaultLookAndFeelDecorated( true ); } if (!Config.isDisableJvmParameterChecks()) From e8218b121307e8620247b04d592a088a17c11cc8 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Wed, 30 Aug 2023 17:55:08 +0200 Subject: [PATCH 062/184] - use reduced timeout client for filmlist reading --- src/main/java/mediathek/filmlisten/reader/FilmListReader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/mediathek/filmlisten/reader/FilmListReader.java b/src/main/java/mediathek/filmlisten/reader/FilmListReader.java index 4cd751e325..ce2b4f46b5 100644 --- a/src/main/java/mediathek/filmlisten/reader/FilmListReader.java +++ b/src/main/java/mediathek/filmlisten/reader/FilmListReader.java @@ -457,7 +457,7 @@ private void processFromWeb(URL source, ListeFilme listeFilme) { .get() .build(); - try (Response response = MVHttpClient.getInstance().getHttpClient().newCall(request).execute(); + try (Response response = MVHttpClient.getInstance().getReducedTimeOutClient().newCall(request).execute(); ResponseBody body = response.body()) { if (response.isSuccessful() && body != null) { final var endRequest = response.request(); From 53c87d8cd36efcaf53460a65de9b3fc1d2ba6d73 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Wed, 30 Aug 2023 18:05:15 +0200 Subject: [PATCH 063/184] - code cleanup --- .../mediathek/tool/http/MVHttpClient.java | 51 +++-------------- .../tool/http/OkHttpProxyAuthenticator.kt | 55 +++++++++++++++++++ 2 files changed, 63 insertions(+), 43 deletions(-) create mode 100644 src/main/java/mediathek/tool/http/OkHttpProxyAuthenticator.kt diff --git a/src/main/java/mediathek/tool/http/MVHttpClient.java b/src/main/java/mediathek/tool/http/MVHttpClient.java index f0cd98a008..2a3b00aecc 100644 --- a/src/main/java/mediathek/tool/http/MVHttpClient.java +++ b/src/main/java/mediathek/tool/http/MVHttpClient.java @@ -6,7 +6,6 @@ import mediathek.tool.dns.IPvPreferenceMode; import okhttp3.Authenticator; import okhttp3.ConnectionSpec; -import okhttp3.Credentials; import okhttp3.OkHttpClient; import okhttp3.logging.HttpLoggingInterceptor; import org.apache.commons.configuration2.Configuration; @@ -21,9 +20,7 @@ public class MVHttpClient { private static final MVHttpClient ourInstance = new MVHttpClient(); - private static final String HTTP_PROXY_AUTHORIZATION = "Proxy-Authorization"; private final Logger logger = LogManager.getLogger(MVHttpClient.class); - private final Configuration config = ApplicationConfiguration.getConfiguration(); private final ByteCounter byteCounter = new ByteCounter(); private OkHttpClient httpClient; private OkHttpClient reducedTimeoutClient; @@ -41,6 +38,7 @@ private MVHttpClient() { } else { //environment variables were not set, use application settings... try { + Configuration config = ApplicationConfiguration.getConfiguration(); proxyHost = config.getString(ApplicationConfiguration.HttpProxy.HOST); proxyPort = config.getString(ApplicationConfiguration.HttpProxy.PORT); if (!proxyHost.isEmpty() && !proxyPort.isEmpty()) { @@ -90,10 +88,12 @@ private OkHttpClient.Builder getDefaultClientBuilder() { var config = ApplicationConfiguration.getConfiguration(); IPvPreferenceMode mode = IPvPreferenceMode.fromString(config.getString(ApplicationConfiguration.APPLICATION_NETWORKING_DNS_MODE, String.valueOf(IPvPreferenceMode.IPV4_ONLY))); - builder.connectTimeout(30, TimeUnit.SECONDS) - .writeTimeout(30, TimeUnit.SECONDS) - .readTimeout(30, TimeUnit.SECONDS) + builder.connectTimeout(10, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + .readTimeout(10, TimeUnit.SECONDS) .socketFactory(byteCounter.socketFactory()) + .followRedirects(true) + .followSslRedirects(true) .dns(new DnsSelector(mode)); return builder; } @@ -102,42 +102,6 @@ public ByteCounter getByteCounter() { return byteCounter; } - private Authenticator createAuthenticator(String prxUser, String prxPassword) { - return (route, response) -> { - if (response.request().header(HTTP_PROXY_AUTHORIZATION) != null) { - return null; // Give up, we've already attempted to authenticate. - } - final String credential = Credentials.basic(prxUser, prxPassword); - return response.request().newBuilder() - .header(HTTP_PROXY_AUTHORIZATION, credential) - .build(); - }; - } - - private Authenticator setupProxyAuthenticator() { - String prxUser = System.getProperty("http.proxyUser"); - String prxPassword = System.getProperty("http.proxyPassword"); - Authenticator proxyAuthenticator = null; - - if (prxUser != null && prxPassword != null && !prxUser.isEmpty() && !prxPassword.isEmpty()) { - //create proxy auth from environment vars - proxyAuthenticator = createAuthenticator(prxUser, prxPassword); - logger.info("Proxy Authentication from environment vars: ({})", prxUser); - } else { - //try to create proxy auth from settings - try { - prxUser = config.getString(ApplicationConfiguration.HttpProxy.USER); - prxPassword = config.getString(ApplicationConfiguration.HttpProxy.PASSWORD); - if (!prxUser.isEmpty() && !prxPassword.isEmpty()) { - proxyAuthenticator = createAuthenticator(prxUser, prxPassword); - logger.info("Proxy Authentication from application settings: ({})", prxUser); - } - } catch (NoSuchElementException ignored) { - } - } - - return proxyAuthenticator; - } /** * Set the proxy parameters on the shared HTTP clients. @@ -145,7 +109,8 @@ private Authenticator setupProxyAuthenticator() { * @param proxy The proxy settings to be used. */ private void setupProxyClients(Proxy proxy) { - final Authenticator proxyAuthenticator = setupProxyAuthenticator(); + var prxManager = new OkHttpProxyAuthenticator(); + final Authenticator proxyAuthenticator = prxManager.getProxyAuthenticator(); OkHttpClient.Builder tmpBuilder; tmpBuilder = getDefaultClientBuilder() diff --git a/src/main/java/mediathek/tool/http/OkHttpProxyAuthenticator.kt b/src/main/java/mediathek/tool/http/OkHttpProxyAuthenticator.kt new file mode 100644 index 0000000000..6cd359a579 --- /dev/null +++ b/src/main/java/mediathek/tool/http/OkHttpProxyAuthenticator.kt @@ -0,0 +1,55 @@ +package mediathek.tool.http + +import mediathek.tool.ApplicationConfiguration +import okhttp3.Authenticator +import okhttp3.Credentials.basic +import okhttp3.Response +import okhttp3.Route +import org.apache.logging.log4j.LogManager + +internal class OkHttpProxyAuthenticator { + private val logger = LogManager.getLogger() + var proxyAuthenticator: Authenticator? = null + private set + + init { + setupProxyAuthenticator() + } + + private fun setupProxyAuthenticator() { + var prxUser = System.getProperty("http.proxyUser") + var prxPassword = System.getProperty("http.proxyPassword") + proxyAuthenticator = null + if (prxUser != null && prxPassword != null && prxUser.isNotEmpty() && prxPassword.isNotEmpty()) { + //create proxy auth from environment vars + proxyAuthenticator = createAuthenticator(prxUser, prxPassword) + logger.info("Proxy Authentication from environment vars: ({})", prxUser) + } else { + //try to create proxy auth from settings + val config = ApplicationConfiguration.getConfiguration() + prxUser = config.getString(ApplicationConfiguration.HttpProxy.USER, "") + prxPassword = config.getString(ApplicationConfiguration.HttpProxy.PASSWORD, "") + if (prxUser.isNotEmpty() && prxPassword.isNotEmpty()) { + proxyAuthenticator = createAuthenticator(prxUser, prxPassword) + logger.info("Proxy Authentication from application settings: ({})", prxUser) + } else + proxyAuthenticator = null + } + } + + private fun createAuthenticator(prxUser: String, prxPassword: String): Authenticator { + return Authenticator { _: Route?, response: Response -> + if (response.request.header(HTTP_PROXY_AUTHORIZATION) != null) { + return@Authenticator null // Give up, we've already attempted to authenticate. + } + val credential = basic(prxUser, prxPassword) + response.request.newBuilder() + .header(HTTP_PROXY_AUTHORIZATION, credential) + .build() + } + } + + companion object { + private const val HTTP_PROXY_AUTHORIZATION = "Proxy-Authorization" + } +} From 10313030f63fb4cfe45e99f19f3fe6874d295fb2 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Wed, 30 Aug 2023 18:13:44 +0200 Subject: [PATCH 064/184] - always use reduced timeout client instead of two different ones -> cleanup --- .../starter/DirectHttpDownload.java | 2 +- .../mediathek/daten/ListePsetVorlagen.java | 4 +-- .../filmlisten/reader/FilmListReader.java | 2 +- .../gui/tabs/tab_film/JDownloadHelper.kt | 2 +- .../javafx/bookmark/BookmarkNoteDialog.java | 2 +- src/main/java/mediathek/tool/FileSize.java | 2 +- .../mediathek/tool/http/MVHttpClient.java | 34 +++---------------- .../SenderIconCacheLoader.java | 2 +- 8 files changed, 13 insertions(+), 37 deletions(-) diff --git a/src/main/java/mediathek/controller/starter/DirectHttpDownload.java b/src/main/java/mediathek/controller/starter/DirectHttpDownload.java index e98c892d45..efcc1f0365 100644 --- a/src/main/java/mediathek/controller/starter/DirectHttpDownload.java +++ b/src/main/java/mediathek/controller/starter/DirectHttpDownload.java @@ -130,7 +130,7 @@ private long getContentLength(@NotNull HttpUrl url) throws IOException { .header("User-Agent", getUserAgent()) .build(); - try (Response response = MVHttpClient.getInstance().getReducedTimeOutClient().newCall(request).execute()) { + try (Response response = MVHttpClient.getInstance().getHttpClient().newCall(request).execute()) { if (response.isSuccessful()) { contentSize = FileSize.getContentLength(response); diff --git a/src/main/java/mediathek/daten/ListePsetVorlagen.java b/src/main/java/mediathek/daten/ListePsetVorlagen.java index b87b80dcc1..8ddf79ff59 100644 --- a/src/main/java/mediathek/daten/ListePsetVorlagen.java +++ b/src/main/java/mediathek/daten/ListePsetVorlagen.java @@ -128,7 +128,7 @@ public boolean loadListOfSets() { var url = Konstanten.URL_MEDIATHEKVIEW_RESOURCES.resolve(Konstanten.PSET_PROGRAM_GROUP_LIST_PATH); assert url != null; Request request = new Request.Builder().url(url).get().build(); - try (Response response = MVHttpClient.getInstance().getReducedTimeOutClient().newCall(request).execute(); + try (Response response = MVHttpClient.getInstance().getHttpClient().newCall(request).execute(); ResponseBody body = response.body()) { if (response.isSuccessful() && body != null) { try (InputStream is = body.byteStream(); @@ -170,7 +170,7 @@ public static ListePset importPsetFile(String dateiUrl, boolean log) { if (NetUtils.isUrl(dateiUrl)) { Request request = new Request.Builder().url(dateiUrl).get().build(); - try (Response response = MVHttpClient.getInstance().getReducedTimeOutClient().newCall(request).execute(); + try (Response response = MVHttpClient.getInstance().getHttpClient().newCall(request).execute(); ResponseBody body = response.body()) { if (response.isSuccessful() && body != null) { try (InputStream is = body.byteStream(); diff --git a/src/main/java/mediathek/filmlisten/reader/FilmListReader.java b/src/main/java/mediathek/filmlisten/reader/FilmListReader.java index ce2b4f46b5..4cd751e325 100644 --- a/src/main/java/mediathek/filmlisten/reader/FilmListReader.java +++ b/src/main/java/mediathek/filmlisten/reader/FilmListReader.java @@ -457,7 +457,7 @@ private void processFromWeb(URL source, ListeFilme listeFilme) { .get() .build(); - try (Response response = MVHttpClient.getInstance().getReducedTimeOutClient().newCall(request).execute(); + try (Response response = MVHttpClient.getInstance().getHttpClient().newCall(request).execute(); ResponseBody body = response.body()) { if (response.isSuccessful() && body != null) { final var endRequest = response.request(); diff --git a/src/main/java/mediathek/gui/tabs/tab_film/JDownloadHelper.kt b/src/main/java/mediathek/gui/tabs/tab_film/JDownloadHelper.kt index d5adf29791..b4163cb491 100644 --- a/src/main/java/mediathek/gui/tabs/tab_film/JDownloadHelper.kt +++ b/src/main/java/mediathek/gui/tabs/tab_film/JDownloadHelper.kt @@ -33,7 +33,7 @@ class JDownloadHelper { .post(formBody) .build() try { - val builder = MVHttpClient.getInstance().reducedTimeOutClient.newBuilder() + val builder = MVHttpClient.getInstance().httpClient.newBuilder() builder.connectTimeout(125, TimeUnit.MILLISECONDS) val client = builder.build() client.newCall(request).execute().use { diff --git a/src/main/java/mediathek/javafx/bookmark/BookmarkNoteDialog.java b/src/main/java/mediathek/javafx/bookmark/BookmarkNoteDialog.java index d38131ce90..7b6d1cea19 100644 --- a/src/main/java/mediathek/javafx/bookmark/BookmarkNoteDialog.java +++ b/src/main/java/mediathek/javafx/bookmark/BookmarkNoteDialog.java @@ -218,7 +218,7 @@ private String searchExpiryDate() { String result = null; if (hasWebURL) { final Request request = new Request.Builder().url(data.getWebUrl()).get().build(); - try (Response response = MVHttpClient.getInstance().getReducedTimeOutClient().newCall(request).execute(); + try (Response response = MVHttpClient.getInstance().getHttpClient().newCall(request).execute(); ResponseBody body = response.body()) { if (response.isSuccessful() && body != null) { try (var is = body.byteStream(); diff --git a/src/main/java/mediathek/tool/FileSize.java b/src/main/java/mediathek/tool/FileSize.java index 3b1ca90b5b..42aa90d2f4 100644 --- a/src/main/java/mediathek/tool/FileSize.java +++ b/src/main/java/mediathek/tool/FileSize.java @@ -86,7 +86,7 @@ public static long getFileSizeFromUrl(@NotNull HttpUrl url) { logger.info("Requesting file size for: {}", url); final Request request = new Request.Builder().url(url).head().build(); long respLength = INVALID_SIZE; - try (Response response = MVHttpClient.getInstance().getReducedTimeOutClient().newCall(request).execute()) { + try (Response response = MVHttpClient.getInstance().getHttpClient().newCall(request).execute()) { if (response.isSuccessful()) { respLength = getContentLength(response); } diff --git a/src/main/java/mediathek/tool/http/MVHttpClient.java b/src/main/java/mediathek/tool/http/MVHttpClient.java index 2a3b00aecc..e043b1ad48 100644 --- a/src/main/java/mediathek/tool/http/MVHttpClient.java +++ b/src/main/java/mediathek/tool/http/MVHttpClient.java @@ -23,7 +23,6 @@ public class MVHttpClient { private final Logger logger = LogManager.getLogger(MVHttpClient.class); private final ByteCounter byteCounter = new ByteCounter(); private OkHttpClient httpClient; - private OkHttpClient reducedTimeoutClient; private MVHttpClient() { String proxyHost = System.getProperty("http.proxyHost"); @@ -88,9 +87,9 @@ private OkHttpClient.Builder getDefaultClientBuilder() { var config = ApplicationConfiguration.getConfiguration(); IPvPreferenceMode mode = IPvPreferenceMode.fromString(config.getString(ApplicationConfiguration.APPLICATION_NETWORKING_DNS_MODE, String.valueOf(IPvPreferenceMode.IPV4_ONLY))); - builder.connectTimeout(10, TimeUnit.SECONDS) - .writeTimeout(10, TimeUnit.SECONDS) - .readTimeout(10, TimeUnit.SECONDS) + builder.connectTimeout(5, TimeUnit.SECONDS) + .writeTimeout(5, TimeUnit.SECONDS) + .readTimeout(2, TimeUnit.SECONDS) .socketFactory(byteCounter.socketFactory()) .followRedirects(true) .followSslRedirects(true) @@ -113,45 +112,22 @@ private void setupProxyClients(Proxy proxy) { final Authenticator proxyAuthenticator = prxManager.getProxyAuthenticator(); OkHttpClient.Builder tmpBuilder; - tmpBuilder = getDefaultClientBuilder() - .proxy(proxy); + tmpBuilder = getDefaultClientBuilder().proxy(proxy); if (proxyAuthenticator != null) tmpBuilder.proxyAuthenticator(proxyAuthenticator); httpClient = tmpBuilder.build(); - - tmpBuilder = getDefaultClientBuilder() - .connectTimeout(5, TimeUnit.SECONDS) - .readTimeout(5, TimeUnit.SECONDS) - .writeTimeout(2, TimeUnit.SECONDS) - .proxy(proxy); - - if (proxyAuthenticator != null) - tmpBuilder.proxyAuthenticator(proxyAuthenticator); - reducedTimeoutClient = tmpBuilder.build(); } /** * Setup HTTP client without proxy settings */ private void setupNonProxyClients() { - httpClient = getDefaultClientBuilder() - .build(); - - reducedTimeoutClient = getDefaultClientBuilder() - .connectTimeout(5, TimeUnit.SECONDS) - .readTimeout(5, TimeUnit.SECONDS) - .writeTimeout(2, TimeUnit.SECONDS) - .build(); - + httpClient = getDefaultClientBuilder().build(); logger.info("MVHttpClient: Proxy not configured"); } public OkHttpClient getHttpClient() { return httpClient; } - - public OkHttpClient getReducedTimeOutClient() { - return reducedTimeoutClient; - } } diff --git a/src/main/java/mediathek/tool/sender_icon_cache/SenderIconCacheLoader.java b/src/main/java/mediathek/tool/sender_icon_cache/SenderIconCacheLoader.java index 58b965a6d3..b25204b876 100644 --- a/src/main/java/mediathek/tool/sender_icon_cache/SenderIconCacheLoader.java +++ b/src/main/java/mediathek/tool/sender_icon_cache/SenderIconCacheLoader.java @@ -49,7 +49,7 @@ public SenderIconCacheLoader(@NotNull AtomicBoolean useLocalIcons) { .get() .build(); - try (Response response = MVHttpClient.getInstance().getReducedTimeOutClient().newCall(request).execute(); + try (Response response = MVHttpClient.getInstance().getHttpClient().newCall(request).execute(); ResponseBody body = response.body()) { if (response.isSuccessful() && body != null) { BufferedImage b_img = ImageIO.read(body.byteStream()); From 5c47c5a07cf58a142978961a3db2feb1a55f3ce3 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Wed, 30 Aug 2023 19:56:32 +0200 Subject: [PATCH 065/184] - use zip file and shared lib version of ffmpeg --- pom.xml | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/pom.xml b/pom.xml index e15a533973..caa30728e6 100755 --- a/pom.xml +++ b/pom.xml @@ -730,27 +730,16 @@ 1.7.0 - download-ffmpeg-exe-intel-from-server - package - - wget - - - https://s3.mvorg.de/res/dev/windows/64/bin/ffmpeg.exe - ${project.build.directory}/res/bin - c075ca784ad26b3ad3f8f49474ee5187 - - - - download-ffprobe-exe-intel-from-server + download-ffmpeg-exe-aarch64-from-server package wget - https://s3.mvorg.de/res/dev/windows/64/bin/ffprobe.exe + https://s3.mvorg.de/res/dev/windows/64/bin/ffmpeg.zip + true ${project.build.directory}/res/bin - 239433c7e3c51021dd678f19d7eaf39e + eec52ae0359df126c5056bc21a652ac0 From d7a1877156ac3779e26880bed1c5293ce085e5bf Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Wed, 30 Aug 2023 20:31:58 +0200 Subject: [PATCH 066/184] - remove 32bit legacy --- .install4j/mediathekview_windows.install4j | 2 -- 1 file changed, 2 deletions(-) diff --git a/.install4j/mediathekview_windows.install4j b/.install4j/mediathekview_windows.install4j index b481a5c4b1..9d4f5139a3 100644 --- a/.install4j/mediathekview_windows.install4j +++ b/.install4j/mediathekview_windows.install4j @@ -17,9 +17,7 @@ - - From 0c0eb99a897151b7f22f845a2e98e255871fe727 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Tue, 19 Sep 2023 10:50:00 +0200 Subject: [PATCH 067/184] - fix analyzer warnings - remove unused code - code refactor --- src/main/java/mediathek/Main.java | 39 +++++++++++-------- .../BlacklistRuleTableModel.java | 5 --- .../cellrenderer/CellRendererDownloads.java | 4 +- .../mediathek/tool/models/TModelFilm.java | 24 ------------ 4 files changed, 23 insertions(+), 49 deletions(-) diff --git a/src/main/java/mediathek/Main.java b/src/main/java/mediathek/Main.java index 0a520832c4..5c788ca824 100644 --- a/src/main/java/mediathek/Main.java +++ b/src/main/java/mediathek/Main.java @@ -29,6 +29,7 @@ import org.apache.logging.log4j.core.config.AppenderRef; import org.apache.logging.log4j.core.filter.ThresholdFilter; import org.apache.logging.log4j.core.layout.PatternLayout; +import org.jetbrains.annotations.NotNull; import picocli.CommandLine; import javax.imageio.ImageIO; @@ -312,27 +313,31 @@ private static void checkJVMSettings() { if (!correctParameters) { //show error dialog logger.warn("Detected incorrect JVM parameters! Please modify your settings"); - var message = "" + - "Inkorrekte/fehlende JVM Parameter erkannt

" + - "Bitte stellen Sie sicher, dass die folgenden Parameter an die JVM übergeben werden:
" + - "
    " + - "
  • -XX:+UseShenandoahGC
  • " + - "
  • -XX:ShenandoahGCHeuristics=compact
  • " + - "
  • -XX:+UseStringDeduplication
  • " + - "
  • -XX:MaxRAMPercentage=XX.X
  • "; - if (SystemUtils.IS_OS_LINUX) { - message += "
  • --add-opens=java.desktop/sun.awt.X11=ALL-UNNAMED
  • "; - } - - message += "

" + - "-Xmx sollte nicht mehr genutzt werden!" + - ""; - - JOptionPane.showMessageDialog(null,message, Konstanten.PROGRAMMNAME, + JOptionPane.showMessageDialog(null,getJvmErrorMessageString(), Konstanten.PROGRAMMNAME, JOptionPane.WARNING_MESSAGE); } } + @NotNull + private static String getJvmErrorMessageString() { + var message = "" + + "Inkorrekte/fehlende JVM Parameter erkannt

" + + "Bitte stellen Sie sicher, dass die folgenden Parameter an die JVM übergeben werden:
" + + "
    " + + "
  • -XX:+UseShenandoahGC
  • " + + "
  • -XX:ShenandoahGCHeuristics=compact
  • " + + "
  • -XX:+UseStringDeduplication
  • " + + "
  • -XX:MaxRAMPercentage=XX.X
  • "; + if (SystemUtils.IS_OS_LINUX) { + message += "
  • --add-opens=java.desktop/sun.awt.X11=ALL-UNNAMED
  • "; + } + + message += "

" + + "-Xmx sollte nicht mehr genutzt werden!" + + ""; + return message; + } + /** * Check if a non-floating point scale factor is set on Linux. * Java 18 VM does not support fractional scaling. diff --git a/src/main/java/mediathek/gui/dialogEinstellungen/BlacklistRuleTableModel.java b/src/main/java/mediathek/gui/dialogEinstellungen/BlacklistRuleTableModel.java index e65383e59e..4c23f61863 100644 --- a/src/main/java/mediathek/gui/dialogEinstellungen/BlacklistRuleTableModel.java +++ b/src/main/java/mediathek/gui/dialogEinstellungen/BlacklistRuleTableModel.java @@ -52,11 +52,6 @@ public String getColumnName(int column) { }; } - @Override - public boolean isCellEditable(int rowIndex, int columnIndex) { - return false; - } - /** * Remove a BlacklistRule from model * diff --git a/src/main/java/mediathek/tool/cellrenderer/CellRendererDownloads.java b/src/main/java/mediathek/tool/cellrenderer/CellRendererDownloads.java index f7f46e57f5..1d55767d8c 100644 --- a/src/main/java/mediathek/tool/cellrenderer/CellRendererDownloads.java +++ b/src/main/java/mediathek/tool/cellrenderer/CellRendererDownloads.java @@ -64,9 +64,7 @@ private void applyHorizontalAlignment(int colIndex) { switch (colIndex) { case DatenDownload.DOWNLOAD_PROGRESS, DatenDownload.DOWNLOAD_FILM_NR, DatenDownload.DOWNLOAD_NR, DatenDownload.DOWNLOAD_DATUM, DatenDownload.DOWNLOAD_ZEIT, DatenDownload.DOWNLOAD_DAUER, DatenDownload.DOWNLOAD_BANDBREITE, - DatenDownload.DOWNLOAD_RESTZEIT -> { - setHorizontalAlignment(SwingConstants.CENTER); - } + DatenDownload.DOWNLOAD_RESTZEIT -> setHorizontalAlignment(SwingConstants.CENTER); case DatenDownload.DOWNLOAD_GROESSE -> setHorizontalAlignment(SwingConstants.RIGHT); } } diff --git a/src/main/java/mediathek/tool/models/TModelFilm.java b/src/main/java/mediathek/tool/models/TModelFilm.java index 04d53b5666..92f116446f 100644 --- a/src/main/java/mediathek/tool/models/TModelFilm.java +++ b/src/main/java/mediathek/tool/models/TModelFilm.java @@ -20,30 +20,6 @@ public TModelFilm(int capacity) { dataList = new ArrayList<>(capacity); } - @Override - public boolean isCellEditable(int i, int j) { - return false; - } - - /** - * Get model row for a requested film nr. - * - * @param reqFilmNr the filmnr of the request - * @return the model row, otherwise -1 - */ - public int getModelRowForFilmNumber(int reqFilmNr) { - int ret = 0; - - for (var film : dataList) { - if (film.getFilmNr() == reqFilmNr) - return ret; - else - ret++; - } - - return -1; - } - @Override public int getRowCount() { return dataList.size(); From 9ccbbb111f1925244372154e0933af4f4ed8817c Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Tue, 19 Sep 2023 12:09:02 +0200 Subject: [PATCH 068/184] - use async ffprobe for film info detection - upgrade FlatLaf --- pom.xml | 2 +- .../gui/dialog/DialogAddDownload.form | 52 ++++--- .../gui/dialog/DialogAddDownload.java | 131 ++++++++++++------ 3 files changed, 115 insertions(+), 70 deletions(-) diff --git a/pom.xml b/pom.xml index caa30728e6..619f60294b 100755 --- a/pom.xml +++ b/pom.xml @@ -93,7 +93,7 @@ 2.11.0 3.12.0 11.1.2 - 3.1.1 + 3.2.1 31.1-jre 1.1.2 2.14.1 diff --git a/src/main/java/mediathek/gui/dialog/DialogAddDownload.form b/src/main/java/mediathek/gui/dialog/DialogAddDownload.form index b247004748..2efab0b3f5 100644 --- a/src/main/java/mediathek/gui/dialog/DialogAddDownload.form +++ b/src/main/java/mediathek/gui/dialog/DialogAddDownload.form @@ -1,6 +1,6 @@ -
+ @@ -301,13 +301,9 @@ - - - - - - + + @@ -322,11 +318,8 @@ - - - - - + + @@ -357,21 +350,26 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/mediathek/gui/dialog/DialogAddDownload.java b/src/main/java/mediathek/gui/dialog/DialogAddDownload.java index 649a4f409c..5692950275 100644 --- a/src/main/java/mediathek/gui/dialog/DialogAddDownload.java +++ b/src/main/java/mediathek/gui/dialog/DialogAddDownload.java @@ -5,6 +5,7 @@ import com.github.kokorin.jaffree.ffprobe.FFprobeResult; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.JdkFutureAdapters; import com.google.common.util.concurrent.ListenableFuture; import mediathek.config.Daten; import mediathek.config.Konstanten; @@ -37,7 +38,9 @@ import java.util.ArrayList; import java.util.Objects; import java.util.Optional; +import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; public class DialogAddDownload extends JDialog { private DatenPset pSet; @@ -76,7 +79,13 @@ private void setupFilmQualityRadioButtons() { @Override public void actionPerformed(ActionEvent e) { setNameFilm(); - lblFilmInfo.setText(""); + lblStatus.setText(""); + lblBusyIndicator.setBusy(false); + lblBusyIndicator.setVisible(false); + if (resultListenableFuture != null) { + resultListenableFuture.cancel(true); + resultListenableFuture = null; + } } }; jRadioButtonAufloesungHd.addActionListener(listener); @@ -92,35 +101,64 @@ public void actionPerformed(ActionEvent e) { } private Path ffprobePath; + private ListenableFuture resultListenableFuture; private void handleRequestLiveFilmInfo() { - setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - var res = getFilmResolution(); var url = datenFilm.getUrlFuerAufloesung(res); - try { - btnRequestLiveInfo.setEnabled(false); - FFprobeResult result = FFprobe.atPath(ffprobePath) - .setShowStreams(true) - .setInput(url) - .execute(); - - var videoStreamResult = result.getStreams().stream().filter(stream -> stream.getCodecType() == StreamType.VIDEO).findAny(); - videoStreamResult.ifPresentOrElse(stream -> { - var fr = stream.getAvgFrameRate().intValue(); - var output = String.format("%dx%d, %d kBit/s, %d fps (avg)", stream.getWidth(), stream.getHeight(), stream.getBitRate() / 1000, fr); - lblFilmInfo.setText(output); - - }, () -> lblFilmInfo.setText("Keine Daten verfügbar.")); - btnRequestLiveInfo.setEnabled(true); - } - catch (Exception ex) { - lblFilmInfo.setText("Abrufen der Infos fehlgeschlagen!"); - lblFilmInfo.setForeground(Color.RED); - logger.error("ffprobe execution failed", ex); - } - setCursor(Cursor.getDefaultCursor()); + btnRequestLiveInfo.setEnabled(false); + lblBusyIndicator.setVisible(true); + lblBusyIndicator.setBusy(true); + lblStatus.setText(""); + + Future resultFuture = FFprobe.atPath(ffprobePath) + .setShowStreams(true) + .setInput(url) + .executeAsync(); + resultListenableFuture = JdkFutureAdapters.listenInPoolThread(resultFuture); + Futures.addCallback(resultListenableFuture, new FutureCallback<>() { + @Override + public void onSuccess(FFprobeResult result) { + var videoStreamResult = result.getStreams().stream().filter(stream -> stream.getCodecType() == StreamType.VIDEO).findAny(); + videoStreamResult.ifPresentOrElse(stream -> { + var fr = stream.getAvgFrameRate().intValue(); + var output = String.format("%dx%d, %d kBit/s, %d fps (avg)", stream.getWidth(), stream.getHeight(), stream.getBitRate() / 1000, fr); + SwingUtilities.invokeLater(() -> { + lblStatus.setForeground(UIManager.getColor("Label.foreground")); + lblStatus.setText(output); + }); + }, () -> SwingUtilities.invokeLater(() -> { + lblStatus.setForeground(UIManager.getColor("Label.foreground")); + lblStatus.setText("Keine Daten verfügbar."); + })); + + SwingUtilities.invokeLater(() -> resetBusyLabelAndButton()); + } + + @Override + public void onFailure(@NotNull Throwable t) { + // show nothing when task was cancelled... + if (t instanceof CancellationException) { + SwingUtilities.invokeLater(() -> { + lblStatus.setText(""); + resetBusyLabelAndButton(); + }); + } + else + SwingUtilities.invokeLater(() -> { + lblStatus.setText("Unbekannter Fehler aufgetreten."); + lblStatus.setForeground(Color.RED); + resetBusyLabelAndButton(); + }); + } + }, Daten.getInstance().getDecoratedPool()); + } + + private void resetBusyLabelAndButton() { + lblBusyIndicator.setBusy(false); + lblBusyIndicator.setVisible(false); + btnRequestLiveInfo.setEnabled(true); } private void detectFfprobeExecutable() { @@ -129,15 +167,21 @@ private void detectFfprobeExecutable() { } catch (Exception ex) { logger.error("ffprobe not found", ex); - lblFilmInfo.setText("Hilfsprogramm nicht gefunden!"); - lblFilmInfo.setForeground(Color.RED); + lblBusyIndicator.setText("Hilfsprogramm nicht gefunden!"); + lblBusyIndicator.setForeground(Color.RED); btnRequestLiveInfo.setEnabled(false); } } - private void setupUI() { - lblFilmInfo.setText(""); + private void setupBusyIndicator() { + lblBusyIndicator.setText(""); + lblBusyIndicator.setBusy(false); + lblBusyIndicator.setVisible(false); + lblStatus.setText(""); + } + private void setupUI() { + setupBusyIndicator(); detectFfprobeExecutable(); // launch async tasks first @@ -693,8 +737,10 @@ private void initComponents() { jRadioButtonAufloesungHd = new javax.swing.JRadioButton(); jRadioButtonAufloesungHoch = new javax.swing.JRadioButton(); jRadioButtonAufloesungKlein = new javax.swing.JRadioButton(); + jPanel3 = new javax.swing.JPanel(); btnRequestLiveInfo = new javax.swing.JButton(); - lblFilmInfo = new javax.swing.JLabel(); + lblBusyIndicator = new org.jdesktop.swingx.JXBusyLabel(); + lblStatus = new javax.swing.JLabel(); jTextFieldSender = new javax.swing.JTextField(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); @@ -819,10 +865,14 @@ private void initComponents() { buttonGroup1.add(jRadioButtonAufloesungKlein); jRadioButtonAufloesungKlein.setText("Niedrig"); + jPanel3.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT)); + btnRequestLiveInfo.setText("Filminformationen abrufen..."); + jPanel3.add(btnRequestLiveInfo); + jPanel3.add(lblBusyIndicator); - lblFilmInfo.setFont(lblFilmInfo.getFont().deriveFont(lblFilmInfo.getFont().getSize()-1f)); - lblFilmInfo.setText("jLabel2"); + lblStatus.setText("jLabel2"); + jPanel3.add(lblStatus); javax.swing.GroupLayout jPanelSizeLayout = new javax.swing.GroupLayout(jPanelSize); jPanelSize.setLayout(jPanelSizeLayout); @@ -837,11 +887,8 @@ private void initComponents() { .addComponent(jRadioButtonAufloesungHoch) .addGap(18, 18, 18) .addComponent(jRadioButtonAufloesungKlein) - .addGap(0, 0, Short.MAX_VALUE)) - .addGroup(jPanelSizeLayout.createSequentialGroup() - .addComponent(btnRequestLiveInfo) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblFilmInfo, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + .addGap(0, 292, Short.MAX_VALUE)) + .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap()) ); jPanelSizeLayout.setVerticalGroup( @@ -852,10 +899,8 @@ private void initComponents() { .addComponent(jRadioButtonAufloesungHd) .addComponent(jRadioButtonAufloesungHoch) .addComponent(jRadioButtonAufloesungKlein)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 15, Short.MAX_VALUE) - .addGroup(jPanelSizeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(btnRequestLiveInfo) - .addComponent(lblFilmInfo)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap()) ); @@ -918,12 +963,14 @@ private void initComponents() { private javax.swing.JCheckBox jCheckBoxSubtitle; private javax.swing.JComboBox jComboBoxPfad; private javax.swing.JComboBox jComboBoxPset; + private javax.swing.JPanel jPanel3; private javax.swing.JPanel jPanelSize; private javax.swing.JRadioButton jRadioButtonAufloesungHd; private javax.swing.JRadioButton jRadioButtonAufloesungHoch; private javax.swing.JRadioButton jRadioButtonAufloesungKlein; private javax.swing.JTextField jTextFieldName; private javax.swing.JTextField jTextFieldSender; - private javax.swing.JLabel lblFilmInfo; + private org.jdesktop.swingx.JXBusyLabel lblBusyIndicator; + private javax.swing.JLabel lblStatus; // End of variables declaration//GEN-END:variables } From 84ff6f9385f7f89dd884f856dec4a4fd4310312d Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Tue, 19 Sep 2023 12:13:11 +0200 Subject: [PATCH 069/184] - use local var --- src/main/java/mediathek/gui/dialog/DialogAddDownload.form | 4 ++++ src/main/java/mediathek/gui/dialog/DialogAddDownload.java | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/mediathek/gui/dialog/DialogAddDownload.form b/src/main/java/mediathek/gui/dialog/DialogAddDownload.form index 2efab0b3f5..60733f8e45 100644 --- a/src/main/java/mediathek/gui/dialog/DialogAddDownload.form +++ b/src/main/java/mediathek/gui/dialog/DialogAddDownload.form @@ -351,6 +351,10 @@ + + + + diff --git a/src/main/java/mediathek/gui/dialog/DialogAddDownload.java b/src/main/java/mediathek/gui/dialog/DialogAddDownload.java index 5692950275..a491d75957 100644 --- a/src/main/java/mediathek/gui/dialog/DialogAddDownload.java +++ b/src/main/java/mediathek/gui/dialog/DialogAddDownload.java @@ -737,7 +737,7 @@ private void initComponents() { jRadioButtonAufloesungHd = new javax.swing.JRadioButton(); jRadioButtonAufloesungHoch = new javax.swing.JRadioButton(); jRadioButtonAufloesungKlein = new javax.swing.JRadioButton(); - jPanel3 = new javax.swing.JPanel(); + javax.swing.JPanel jPanel3 = new javax.swing.JPanel(); btnRequestLiveInfo = new javax.swing.JButton(); lblBusyIndicator = new org.jdesktop.swingx.JXBusyLabel(); lblStatus = new javax.swing.JLabel(); @@ -963,7 +963,6 @@ private void initComponents() { private javax.swing.JCheckBox jCheckBoxSubtitle; private javax.swing.JComboBox jComboBoxPfad; private javax.swing.JComboBox jComboBoxPset; - private javax.swing.JPanel jPanel3; private javax.swing.JPanel jPanelSize; private javax.swing.JRadioButton jRadioButtonAufloesungHd; private javax.swing.JRadioButton jRadioButtonAufloesungHoch; From 2d7514ccf660730aafdc45737f6965a09dcc20e7 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Wed, 20 Sep 2023 23:42:19 +0200 Subject: [PATCH 070/184] - update progress components on LaF change --- src/main/java/mediathek/mainwindow/MediathekGui.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/mediathek/mainwindow/MediathekGui.java b/src/main/java/mediathek/mainwindow/MediathekGui.java index 9c99d9ecf2..471762ec1d 100644 --- a/src/main/java/mediathek/mainwindow/MediathekGui.java +++ b/src/main/java/mediathek/mainwindow/MediathekGui.java @@ -149,6 +149,12 @@ public MediathekGui() { setupScrollBarWidth(); UIManager.put("TabbedPane.showTabSeparators", true); + UIManager.addPropertyChangeListener(evt -> { + if (evt.getPropertyName().equalsIgnoreCase("lookAndFeel")) { + SwingUtilities.updateComponentTreeUI(progressLabel); + SwingUtilities.updateComponentTreeUI(progressBar); + } + }); setupAlternatingRowColors(); From f91d53411eb70bfc2161afe49eb2d703f286f6b2 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Thu, 21 Sep 2023 11:35:25 +0200 Subject: [PATCH 071/184] - rename "Film aufzeichnen" to "Film downloaden" -> fixes different naming - fix incorrect foreground colors for context menu during darkmode changes. --- CHANGELOG.md | 2 ++ .../mediathek/gui/tabs/tab_film/GuiFilme.java | 29 ++++--------------- 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f564c6d6cc..2495bef27f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ - **BUGFIX:** Im Zeilenumbruch-Modus sind nun 3 Zeilen Standard statt vorher vier. - **BUGFIX:** Im *Zeilen umbrechen*-Modus des Tab Filme werden die Einträge nun nicht mehr vertikal zentriert. - **BUGFIX:** Im *Zeilen umbrechen*-Modus des Tab Downloads werden die Einträge nun einheitlich dargestellt. +- **BUGFIX:** Im Tab Filme wurde der Kontextmenüeintrag "Film aufzeichnen" konform zum Menüeintrag in "Film downloaden" angepasst. +- **BUGFIX:** Im Tab Filme wurden die Darstellungsfehler im Kontextmenü beim Hell/Dunkel-Wechsel korrigiert. - **FEATURE:** In der Filmliste kann die Darstellung der Info-Icons nun so konfiguriert werden, dass sie links oder Rechts des Titels dargestellt werden. Dies erfolgt mit der Checkbox unter *Einstellungen/Allgemein->Info-Icons der Listen rechts darstellen*. - **FEATURE(Windows/Linux):** Geänderte Programmschriftart und -größe wird nun gespeichert und beim Start wiederhergestellt. - **FEATURE:** Die URLs des selektierten Films können nun für HQ und normale Auflösung mittels `Strg+Alt+Shift+H` bzw. `Strg+Alt+Shift+N` oder wie bisher über das Kontextmenü in die Zwischenablage kopiert werden. Unter macOS ersetze `Strg` mit `Command`. diff --git a/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java b/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java index 6edc1548d1..c6a4d6db9d 100644 --- a/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java +++ b/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java @@ -1196,22 +1196,13 @@ class TableContextMenuHandler extends MouseAdapter { private final BeobBlacklist beobBlacklistSender = new BeobBlacklist(true, false); private final BeobBlacklist beobBlacklistSenderThema = new BeobBlacklist(true, true); private final BeobBlacklist beobBlacklistThema = new BeobBlacklist(false, true); - private final JMenuItem miSave = createSaveFilmItem(); - private final JMenuItem miBookmark = createBookmarkFilmItem(); private final ActionListener unseenActionListener = new BeobHistory(false); private final ActionListener seenActionListener = new BeobHistory(true); private final JDownloadHelper jDownloadHelper = new JDownloadHelper(); private final DownloadSubtitleAction downloadSubtitleAction = new DownloadSubtitleAction(GuiFilme.this); private Point p; - private JMenuItem miPrintTable; TableContextMenuHandler() { - createStaticMenuEntries(); - } - - private void createStaticMenuEntries() { - miPrintTable = new JMenuItem("Tabelle drucken"); - miPrintTable.addActionListener(beobPrint); } @Override @@ -1281,20 +1272,6 @@ private void buttonTable(int row, int column) { } } - private JMenuItem createSaveFilmItem() { - JMenuItem item = new JMenuItem("Film aufzeichnen"); - item.setIcon(SVGIconUtilities.createSVGIcon("icons/fontawesome/download.svg")); - item.addActionListener(saveFilmAction); - return item; - } - - private JMenuItem createBookmarkFilmItem() { - JMenuItem item = new JMenuItem("Film merken"); - item.setIcon(SVGIconUtilities.createSVGIcon("icons/fontawesome/bookmark.svg")); - item.addActionListener(bookmarkFilmAction); - return item; - } - private void showMenu(MouseEvent evt) { p = evt.getPoint(); final int nr = tabelle.rowAtPoint(p); @@ -1305,7 +1282,9 @@ private void showMenu(MouseEvent evt) { JPopupMenu jPopupMenu = new JPopupMenu(); jPopupMenu.add(playFilmAction); - jPopupMenu.add(miSave); + jPopupMenu.add(saveFilmAction); + + JMenuItem miBookmark = new JMenuItem(bookmarkFilmAction); jPopupMenu.add(miBookmark); jPopupMenu.addSeparator(); @@ -1392,6 +1371,8 @@ private void showMenu(MouseEvent evt) { }); // Drucken + var miPrintTable = new JMenuItem("Tabelle drucken"); + miPrintTable.addActionListener(beobPrint); jPopupMenu.add(miPrintTable); jPopupMenu.add(mediathekGui.showFilmInformationAction); From 115d53068672c33b17d52a12b3cee752a6641c09 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Thu, 21 Sep 2023 11:50:17 +0200 Subject: [PATCH 072/184] - code refactor pset foreground color --- src/main/java/mediathek/daten/DatenPset.java | 13 +++++++++++++ .../java/mediathek/gui/tabs/tab_film/GuiFilme.java | 14 ++++---------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/main/java/mediathek/daten/DatenPset.java b/src/main/java/mediathek/daten/DatenPset.java index 575d1b1ee8..f50e2f06ab 100644 --- a/src/main/java/mediathek/daten/DatenPset.java +++ b/src/main/java/mediathek/daten/DatenPset.java @@ -30,6 +30,7 @@ import javax.swing.*; import java.awt.*; import java.util.Arrays; +import java.util.Optional; public class DatenPset implements Comparable { @@ -227,6 +228,18 @@ public DatenPset copy() { return ret; } + /** + * Return the specified foreground color if present. + * @return the requested foreground color for the PSet. + */ + public Optional getForegroundColor() { + return Optional.ofNullable(getFarbe()); + } + + public String getName() { + return arr[PROGRAMMSET_NAME]; + } + public Color getFarbe() { Color ret = null; String r, g, b; diff --git a/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java b/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java index c6a4d6db9d..8b491d8236 100644 --- a/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java +++ b/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java @@ -1325,17 +1325,11 @@ private void showMenu(MouseEvent evt) { // ein "leeres" Pset, Platzhalter continue; } - Color col = pset.getFarbe(); - JMenuItem item = new JMenuItem(pset.arr[DatenPset.PROGRAMMSET_NAME]); - if (pset.getListeProg().isEmpty()) { - if (col != null) { - item.setForeground(col); - } - } else { + + JMenuItem item = new JMenuItem(pset.getName()); + pset.getForegroundColor().ifPresent(item::setForeground); + if (!pset.getListeProg().isEmpty()) { item.addActionListener(l -> playerStarten(pset)); - if (col != null) { - item.setBackground(col); - } } submenue.add(item); } From 8e5a993a96c9d456de086fae32380e2d5fbe00d6 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Thu, 21 Sep 2023 12:15:58 +0200 Subject: [PATCH 073/184] - pset getName refactor --- src/main/java/mediathek/daten/DatenPset.java | 4 ++-- .../java/mediathek/daten/ListeDownloads.java | 4 ++-- src/main/java/mediathek/daten/ListePset.java | 4 ++-- .../gui/dialog/DialogAddDownload.java | 2 +- .../dialogEinstellungen/PanelPsetKurz.java | 2 +- .../dialogEinstellungen/PanelPsetLang.java | 18 +++++++++--------- .../mediathek/gui/tabs/tab_film/GuiFilme.java | 2 +- .../gui/tabs/tab_film/PsetButtonsPanel.java | 19 ++++++++----------- .../mediathek/update/ProgramUpdateCheck.java | 2 +- 9 files changed, 27 insertions(+), 30 deletions(-) diff --git a/src/main/java/mediathek/daten/DatenPset.java b/src/main/java/mediathek/daten/DatenPset.java index f50e2f06ab..458be7e6af 100644 --- a/src/main/java/mediathek/daten/DatenPset.java +++ b/src/main/java/mediathek/daten/DatenPset.java @@ -145,14 +145,14 @@ public boolean istAbo() { public boolean isLabel() { //if program list is empty AND there is a name -> label if (this.listeProg.isEmpty()) { - return !this.arr[PROGRAMMSET_NAME].isEmpty(); + return !getName().isEmpty(); } return false; } public boolean isFreeLine() { //Wenn die Programmgruppe keinen Namen hat, leere Zeile - return this.arr[PROGRAMMSET_NAME].isEmpty(); + return getName().isEmpty(); } public void setAbspielen() { diff --git a/src/main/java/mediathek/daten/ListeDownloads.java b/src/main/java/mediathek/daten/ListeDownloads.java index c2739f63e9..4c721cbf84 100644 --- a/src/main/java/mediathek/daten/ListeDownloads.java +++ b/src/main/java/mediathek/daten/ListeDownloads.java @@ -385,9 +385,9 @@ public synchronized void abosSuchen(JFrame parent) { //diesen Film in die Downloadliste eintragen abo.setDownDatum(todayDateStr); - if (!abo.getPsetName().equals(pSet.arr[DatenPset.PROGRAMMSET_NAME])) { + if (!abo.getPsetName().equals(pSet.getName())) { // nur den Namen anpassen, falls geändert - abo.setPsetName(pSet.arr[DatenPset.PROGRAMMSET_NAME]); + abo.setPsetName(pSet.getName()); } //dann in die Liste schreiben diff --git a/src/main/java/mediathek/daten/ListePset.java b/src/main/java/mediathek/daten/ListePset.java index 8dc961991b..8eb28d9c6c 100644 --- a/src/main/java/mediathek/daten/ListePset.java +++ b/src/main/java/mediathek/daten/ListePset.java @@ -104,7 +104,7 @@ public DatenPset getPsetAbo(String name) { } else { for (DatenPset pset : this) { if (pset.istAbo()) { - if (pset.arr[DatenPset.PROGRAMMSET_NAME].equals(name)) { + if (pset.getName().equals(name)) { ret = pset; } } @@ -148,7 +148,7 @@ public String[] getObjectDataCombo() { int i = 0; object = new String[this.size()]; for (DatenPset datenPset : this) { - object[i] = datenPset.arr[DatenPset.PROGRAMMSET_NAME]; + object[i] = datenPset.getName(); ++i; } return object; diff --git a/src/main/java/mediathek/gui/dialog/DialogAddDownload.java b/src/main/java/mediathek/gui/dialog/DialogAddDownload.java index a491d75957..331bd5aac3 100644 --- a/src/main/java/mediathek/gui/dialog/DialogAddDownload.java +++ b/src/main/java/mediathek/gui/dialog/DialogAddDownload.java @@ -319,7 +319,7 @@ private void setupPSetComboBox() { jComboBoxPset.setModel(new DefaultComboBoxModel<>(listeSpeichern.getObjectDataCombo())); if (pSet != null) { - jComboBoxPset.setSelectedItem(pSet.arr[DatenPset.PROGRAMMSET_NAME]); + jComboBoxPset.setSelectedItem(pSet.getName()); } else { pSet = listeSpeichern.get(jComboBoxPset.getSelectedIndex()); } diff --git a/src/main/java/mediathek/gui/dialogEinstellungen/PanelPsetKurz.java b/src/main/java/mediathek/gui/dialogEinstellungen/PanelPsetKurz.java index 1e38d85ce8..83d0a5d2b0 100644 --- a/src/main/java/mediathek/gui/dialogEinstellungen/PanelPsetKurz.java +++ b/src/main/java/mediathek/gui/dialogEinstellungen/PanelPsetKurz.java @@ -87,7 +87,7 @@ private void init() { pSet = null; } if (pSet != null) { - jTextFieldName.setText(pSet.arr[DatenPset.PROGRAMMSET_NAME]); + jTextFieldName.setText(pSet.getName()); jTextArea1.setText(pSet.arr[DatenPset.PROGRAMMSET_BESCHREIBUNG]); if (!pSet.istSpeichern() && pSet.arr[DatenPset.PROGRAMMSET_ZIEL_PFAD].equals("")) { jTextFieldZiel.setEditable(false); diff --git a/src/main/java/mediathek/gui/dialogEinstellungen/PanelPsetLang.java b/src/main/java/mediathek/gui/dialogEinstellungen/PanelPsetLang.java index a20840a70c..c90c889fed 100644 --- a/src/main/java/mediathek/gui/dialogEinstellungen/PanelPsetLang.java +++ b/src/main/java/mediathek/gui/dialogEinstellungen/PanelPsetLang.java @@ -400,7 +400,7 @@ private void init() { if (row != -1) { datenPset = listePset.get(tabellePset.convertRowIndexToModel(row)); tabellePset.getModel().setValueAt(jTextFieldSetName.getText(), tabellePset.convertRowIndexToModel(row), DatenPset.PROGRAMMSET_NAME); - jTabbedPane.setTitleAt(0, "Set Name: " + datenPset.arr[DatenPset.PROGRAMMSET_NAME]); + jTabbedPane.setTitleAt(0, "Set Name: " + datenPset.getName()); } } } @@ -428,7 +428,7 @@ public void programmePruefen() { if (!datenPset.isFreeLine() && !datenPset.isLabel()) { // nur wenn kein Label oder freeline text.append("++++++++++++++++++++++++++++++++++++++++++++" + '\n'); - text.append(PIPE + "Programmgruppe: ").append(datenPset.arr[DatenPset.PROGRAMMSET_NAME]).append('\n'); + text.append(PIPE + "Programmgruppe: ").append(datenPset.getName()).append('\n'); String zielPfad = datenPset.arr[DatenPset.PROGRAMMSET_ZIEL_PFAD]; if (datenPset.progsContainPath()) { // beim nur Abspielen wird er nicht gebraucht @@ -552,7 +552,7 @@ private void tabelleProgramme() { GuiFunktionen.enableComponents(jTabbedPane, pSet != null); jButtonAbspielen.setBackground(null); if (pSet != null) { - jTabbedPane.setTitleAt(0, "Set Name: " + pSet.arr[DatenPset.PROGRAMMSET_NAME]); + jTabbedPane.setTitleAt(0, "Set Name: " + pSet.getName()); if (pSet.arr[DatenPset.PROGRAMMSET_MAX_LAENGE].equals("")) { jSpinnerLaenge.setValue(Konstanten.LAENGE_DATEINAME); pSet.arr[DatenPset.PROGRAMMSET_MAX_LAENGE] = String.valueOf(Konstanten.LAENGE_DATEINAME); @@ -572,8 +572,8 @@ private void tabelleProgramme() { jCheckBoxSubtitle.setSelected(Boolean.parseBoolean(pSet.arr[DatenPset.PROGRAMMSET_SUBTITLE])); jCheckBoxSpotlight.setEnabled(SystemUtils.IS_OS_MAC_OSX); jCheckBoxSpotlight.setSelected(Boolean.parseBoolean(pSet.arr[DatenPset.PROGRAMMSET_SPOTLIGHT])); - jScrollPane1.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Set Name: " + pSet.arr[DatenPset.PROGRAMMSET_NAME], javax.swing.border.TitledBorder.LEFT, javax.swing.border.TitledBorder.TOP)); - jTextFieldSetName.setText(pSet.arr[DatenPset.PROGRAMMSET_NAME]); + jScrollPane1.setBorder(BorderFactory.createTitledBorder(null, "Set Name: " + pSet.getName(), TitledBorder.LEFT, TitledBorder.TOP)); + jTextFieldSetName.setText(pSet.getName()); tfGruppeDirektSuffix.setText(pSet.arr[DatenPset.PROGRAMMSET_SUFFIX_DIREKT]); tfGruppeDirektPraefix.setText(pSet.arr[DatenPset.PROGRAMMSET_PRAEFIX_DIREKT]); tfGruppeZielName.setText(pSet.arr[DatenPset.PROGRAMMSET_ZIEL_DATEINAME]); @@ -718,7 +718,7 @@ private void setLoeschen() { String text; if (rows.length == 1) { pSet = listePset.get(tabellePset.convertRowIndexToModel(rows[0])); - text = pSet.arr[DatenPset.PROGRAMMSET_NAME]; + text = pSet.getName(); } else { text = rows.length + " Set löschen?"; } @@ -750,7 +750,7 @@ private void setExport() { } } - final var entryName = liste.get(0).arr[DatenPset.PROGRAMMSET_NAME]; + final var entryName = liste.get(0).getName(); String name = entryName.isEmpty() ? "Name.xml" : entryName + ".xml"; var fileName = FilenameUtils.replaceLeerDateiname(name, false, Boolean.parseBoolean(MVConfig.get(MVConfig.Configs.SYSTEM_USE_REPLACETABLE)), @@ -870,7 +870,7 @@ private void setNamePruefen() { if (row != -1) { int foundgruppe = 0; for (DatenPset gruppe : listePset) { - if (jTextFieldSetName.getText().equals(gruppe.arr[DatenPset.PROGRAMMSET_NAME])) { + if (jTextFieldSetName.getText().equals(gruppe.getName())) { ++foundgruppe; } } @@ -892,7 +892,7 @@ private void eingabe() { datenPset.arr[psetIndex] = textComponent.getText(); if (psetIndex == DatenPset.PROGRAMMSET_NAME) { tabellePset.getModel().setValueAt(jTextFieldSetName.getText(), modelIndex, DatenPset.PROGRAMMSET_NAME); - jTabbedPane.setTitleAt(0, "Set Name: " + datenPset.arr[DatenPset.PROGRAMMSET_NAME]); + jTabbedPane.setTitleAt(0, "Set Name: " + datenPset.getName()); } if (fireUpdate) notifyProgramSetChanged(); diff --git a/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java b/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java index 8b491d8236..48cde8dfbf 100644 --- a/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java +++ b/src/main/java/mediathek/gui/tabs/tab_film/GuiFilme.java @@ -1321,7 +1321,7 @@ private void showMenu(MouseEvent evt) { jPopupMenu.add(submenue); ListePset liste = Daten.listePset.getListeButton(); for (DatenPset pset : liste) { - if (pset.getListeProg().isEmpty() && pset.arr[DatenPset.PROGRAMMSET_NAME].isEmpty()) { + if (pset.getListeProg().isEmpty() && pset.getName().isEmpty()) { // ein "leeres" Pset, Platzhalter continue; } diff --git a/src/main/java/mediathek/gui/tabs/tab_film/PsetButtonsPanel.java b/src/main/java/mediathek/gui/tabs/tab_film/PsetButtonsPanel.java index 97d07614ed..b473ebe5c3 100644 --- a/src/main/java/mediathek/gui/tabs/tab_film/PsetButtonsPanel.java +++ b/src/main/java/mediathek/gui/tabs/tab_film/PsetButtonsPanel.java @@ -1,7 +1,6 @@ package mediathek.gui.tabs.tab_film; import mediathek.config.Daten; -import mediathek.daten.DatenPset; import mediathek.gui.messages.ProgramSetChangedEvent; import mediathek.tool.MessageBus; import net.engio.mbassy.listener.Handler; @@ -50,21 +49,19 @@ protected void setupButtonLayout() { btnPanel.removeAll(); for (var pset : Daten.listePset.getListeButton()) { - final var psetName = pset.arr[DatenPset.PROGRAMMSET_NAME]; - final var psetColor = pset.getFarbe(); if (!pset.isFreeLine()) { + JComponent comp; + if (pset.isLabel()) { - var l = new JLabel(psetName); - if (psetColor != null) - l.setForeground(psetColor); - btnPanel.add(l); + comp = new JLabel(pset.getName()); } else { - var b = new JButton(psetName); - if (psetColor != null) - b.setBackground(psetColor); + var b = new JButton(pset.getName()); b.addActionListener(l -> guiFilme.playerStarten(pset)); - btnPanel.add(b); + comp = b; } + + pset.getForegroundColor().ifPresent(comp::setForeground); + btnPanel.add(comp); } else { btnPanel.add(new JLabel("")); } diff --git a/src/main/java/mediathek/update/ProgramUpdateCheck.java b/src/main/java/mediathek/update/ProgramUpdateCheck.java index c1f94475f3..f057805b20 100644 --- a/src/main/java/mediathek/update/ProgramUpdateCheck.java +++ b/src/main/java/mediathek/update/ProgramUpdateCheck.java @@ -93,7 +93,7 @@ private void checkForPsetUpdates() { } // damit man sie auch findet :) String date = new SimpleDateFormat("dd.MM.yyyy").format(new Date()); - listePsetStandard.forEach((psNew) -> psNew.arr[DatenPset.PROGRAMMSET_NAME] = psNew.arr[DatenPset.PROGRAMMSET_NAME] + ", neu: " + date); + listePsetStandard.forEach((psNew) -> psNew.arr[DatenPset.PROGRAMMSET_NAME] = psNew.getName() + ", neu: " + date); } GuiFunktionenProgramme.addSetVorlagen(MediathekGui.ui(), Daten.getInstance(), listePsetStandard, true); // damit auch AddOns geladen werden logger.info("Setanlegen: OK"); From 912d359da6a18cbbf7eb2acd0bf0b1985f8f7831 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Thu, 21 Sep 2023 13:16:12 +0200 Subject: [PATCH 074/184] DialogAddDownload: - fix button alignment - fix analyzer warning - fix some layout inconsistencies --- .../gui/dialog/DialogAddDownload.form | 177 +++++++++--------- .../gui/dialog/DialogAddDownload.java | 113 +++++------ 2 files changed, 140 insertions(+), 150 deletions(-) diff --git a/src/main/java/mediathek/gui/dialog/DialogAddDownload.form b/src/main/java/mediathek/gui/dialog/DialogAddDownload.form index 60733f8e45..4d3a6e397b 100644 --- a/src/main/java/mediathek/gui/dialog/DialogAddDownload.form +++ b/src/main/java/mediathek/gui/dialog/DialogAddDownload.form @@ -35,21 +35,25 @@ - + - - - - - - + + + + + + + + + + + + - - @@ -109,15 +113,9 @@ - + - - - - - - - + @@ -126,7 +124,7 @@ - + @@ -141,16 +139,14 @@ - - - - - + + + - + - + @@ -162,12 +158,6 @@ - - - - - - @@ -186,23 +176,6 @@ - - - - - - - - - - - - - - - - - @@ -224,40 +197,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + @@ -278,6 +220,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -301,7 +310,7 @@ - + @@ -369,7 +378,7 @@ - + diff --git a/src/main/java/mediathek/gui/dialog/DialogAddDownload.java b/src/main/java/mediathek/gui/dialog/DialogAddDownload.java index 331bd5aac3..f04177abbc 100644 --- a/src/main/java/mediathek/gui/dialog/DialogAddDownload.java +++ b/src/main/java/mediathek/gui/dialog/DialogAddDownload.java @@ -421,6 +421,7 @@ private void setupZielButton() { } private void setupDeleteHistoryButton() { + jButtonDelHistory.setText(""); jButtonDelHistory.setIcon(SVGIconUtilities.createSVGIcon("icons/fontawesome/trash-can.svg")); jButtonDelHistory.addActionListener(e -> { MVConfig.add(MVConfig.Configs.SYSTEM_DIALOG_DOWNLOAD__PFADE_ZUM_SPEICHERN, ""); @@ -453,7 +454,7 @@ private void setNameFilm() { stopBeob = true; datenDownload = new DatenDownload(pSet, datenFilm, DatenDownload.QUELLE_DOWNLOAD, null, "", "", getFilmResolution().toString()); if (datenDownload.arr[DatenDownload.DOWNLOAD_ZIEL_DATEINAME].isEmpty()) { - // dann wird nicht gespeichert ==> eigenntlich falsche Seteinstellungen?? + // dann wird nicht gespeichert → eigentlich falsche Seteinstellungen? jTextFieldName.setEnabled(false); jComboBoxPfad.setEnabled(false); jButtonZiel.setEnabled(false); @@ -550,7 +551,7 @@ private void calculateAndCheckDiskSpace() { } } } catch (Exception ex) { - ex.printStackTrace(); + logger.error("calculateAndCheckDiskSpace()", ex); } } @@ -722,17 +723,20 @@ private void initComponents() { jCheckBoxStarten = new javax.swing.JCheckBox(); javax.swing.JPanel jPanel1 = new javax.swing.JPanel(); jTextFieldName = new javax.swing.JTextField(); - jButtonZiel = new javax.swing.JButton(); javax.swing.JLabel jLabel1 = new javax.swing.JLabel(); javax.swing.JLabel jLabel4 = new javax.swing.JLabel(); - jComboBoxPfad = new javax.swing.JComboBox<>(); - jButtonDelHistory = new javax.swing.JButton(); javax.swing.JLabel jLabelSet = new javax.swing.JLabel(); jComboBoxPset = new javax.swing.JComboBox<>(); javax.swing.JPanel jPanel2 = new javax.swing.JPanel(); jCheckBoxInfodatei = new javax.swing.JCheckBox(); jCheckBoxPfadSpeichern = new javax.swing.JCheckBox(); jCheckBoxSubtitle = new javax.swing.JCheckBox(); + javax.swing.JPanel jPanel4 = new javax.swing.JPanel(); + jComboBoxPfad = new javax.swing.JComboBox<>(); + javax.swing.Box.Filler filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 32767)); + jButtonZiel = new javax.swing.JButton(); + javax.swing.Box.Filler filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 0), new java.awt.Dimension(5, 32767)); + jButtonDelHistory = new javax.swing.JButton(); jPanelSize = new javax.swing.JPanel(); jRadioButtonAufloesungHd = new javax.swing.JRadioButton(); jRadioButtonAufloesungHoch = new javax.swing.JRadioButton(); @@ -754,54 +758,38 @@ private void initComponents() { jCheckBoxStarten.setSelected(true); jCheckBoxStarten.setText("Download sofort starten"); - jButtonZiel.setText("File"); - jButtonZiel.setToolTipText("Zielpfad auswählen"); - jLabel1.setText("Zielpfad:"); jLabel4.setText("Dateiname:"); - jComboBoxPfad.setEditable(true); - - jButtonDelHistory.setIcon(new javax.swing.ImageIcon(getClass().getResource("/mediathek/res/muster/button-del.png"))); // NOI18N - jButtonDelHistory.setToolTipText("History löschen"); - jLabelSet.setText("Set:"); + jPanel2.setLayout(new java.awt.GridLayout(2, 2)); + jCheckBoxInfodatei.setText("Lege Infodatei an"); jCheckBoxInfodatei.setToolTipText("Erzeugt eine Infodatei im Format \"Infodatei.txt\""); + jPanel2.add(jCheckBoxInfodatei); jCheckBoxPfadSpeichern.setText("Zielpfad speichern"); + jPanel2.add(jCheckBoxPfadSpeichern); jCheckBoxSubtitle.setText("Untertitel speichern: \"Filmname.xxx\""); + jPanel2.add(jCheckBoxSubtitle); - javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); - jPanel2.setLayout(jPanel2Layout); - jPanel2Layout.setHorizontalGroup( - jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel2Layout.createSequentialGroup() - .addContainerGap() - .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel2Layout.createSequentialGroup() - .addComponent(jCheckBoxSubtitle) - .addGap(0, 0, Short.MAX_VALUE)) - .addGroup(jPanel2Layout.createSequentialGroup() - .addComponent(jCheckBoxInfodatei) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 295, Short.MAX_VALUE) - .addComponent(jCheckBoxPfadSpeichern))) - .addContainerGap()) - ); - jPanel2Layout.setVerticalGroup( - jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel2Layout.createSequentialGroup() - .addContainerGap() - .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jCheckBoxPfadSpeichern) - .addComponent(jCheckBoxInfodatei)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(jCheckBoxSubtitle) - .addContainerGap()) - ); + jPanel4.setLayout(new javax.swing.BoxLayout(jPanel4, javax.swing.BoxLayout.LINE_AXIS)); + + jComboBoxPfad.setEditable(true); + jPanel4.add(jComboBoxPfad); + jPanel4.add(filler1); + + jButtonZiel.setText("F"); + jButtonZiel.setToolTipText("Zielpfad auswählen"); + jPanel4.add(jButtonZiel); + jPanel4.add(filler2); + + jButtonDelHistory.setText("H"); + jButtonDelHistory.setToolTipText("History löschen"); + jPanel4.add(jButtonDelHistory); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); @@ -814,20 +802,15 @@ private void initComponents() { .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabelSet) .addComponent(jLabel1)) - .addGap(30, 30, 30) + .addGap(20, 20, 20) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(jComboBoxPfad, 0, 374, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jButtonZiel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jButtonDelHistory)) + .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jComboBoxPset, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(jLabel4) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jTextFieldName)) - .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 622, Short.MAX_VALUE)) .addContainerGap()) ); jPanel1Layout.setVerticalGroup( @@ -838,12 +821,10 @@ private void initComponents() { .addComponent(jLabelSet) .addComponent(jComboBoxPset, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) - .addComponent(jLabel1) - .addComponent(jButtonZiel) - .addComponent(jComboBoxPfad, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(jButtonDelHistory)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel1)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) .addComponent(jLabel4) .addComponent(jTextFieldName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) @@ -852,8 +833,6 @@ private void initComponents() { .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); - jPanel1Layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {jButtonZiel, jTextFieldName}); - jPanelSize.setBorder(javax.swing.BorderFactory.createTitledBorder("Download-Qualität")); buttonGroup1.add(jRadioButtonAufloesungHd); @@ -871,7 +850,7 @@ private void initComponents() { jPanel3.add(btnRequestLiveInfo); jPanel3.add(lblBusyIndicator); - lblStatus.setText("jLabel2"); + lblStatus.setText("status"); jPanel3.add(lblStatus); javax.swing.GroupLayout jPanelSizeLayout = new javax.swing.GroupLayout(jPanelSize); @@ -887,7 +866,7 @@ private void initComponents() { .addComponent(jRadioButtonAufloesungHoch) .addGap(18, 18, 18) .addComponent(jRadioButtonAufloesungKlein) - .addGap(0, 292, Short.MAX_VALUE)) + .addGap(0, 0, Short.MAX_VALUE)) .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap()) ); @@ -917,15 +896,17 @@ private void initComponents() { .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(jPanelSize, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(jTextFieldSender) .addGroup(layout.createSequentialGroup() - .addComponent(jCheckBoxStarten) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(jButtonOk, javax.swing.GroupLayout.PREFERRED_SIZE, 93, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jButtonAbbrechen))) - .addContainerGap()) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jTextFieldSender) + .addComponent(jPanelSize, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(jCheckBoxStarten) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jButtonOk, javax.swing.GroupLayout.PREFERRED_SIZE, 93, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButtonAbbrechen))) + .addContainerGap()))) ); layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jButtonAbbrechen, jButtonOk}); From c20a36892f3d4b38b029000756f1cdccaf43773b Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Thu, 21 Sep 2023 17:33:17 +0200 Subject: [PATCH 075/184] - bump library versions --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 619f60294b..1404353171 100755 --- a/pom.xml +++ b/pom.xml @@ -94,9 +94,9 @@ 3.12.0 11.1.2 3.2.1 - 31.1-jre + 32.1.2-jre 1.1.2 - 2.14.1 + 2.15.2 2022.06.03 20.0.1 1.3 @@ -114,11 +114,11 @@ 3.2.4 3.2.1 3.0.0-M5 - 11.0 + 11.1 4.10.0 5.0.0-alpha.10 4.7.0 - 3.42.0.0 + 3.43.0.0 1.9 mediathek.Main From b487f0ae0aa4a1d781defbc022e813506dc9f7e6 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Fri, 22 Sep 2023 07:54:43 +0200 Subject: [PATCH 076/184] - code refactor --- .../mediathek/mainwindow/MediathekGui.java | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/main/java/mediathek/mainwindow/MediathekGui.java b/src/main/java/mediathek/mainwindow/MediathekGui.java index 471762ec1d..00b3e028c6 100644 --- a/src/main/java/mediathek/mainwindow/MediathekGui.java +++ b/src/main/java/mediathek/mainwindow/MediathekGui.java @@ -201,10 +201,7 @@ public MediathekGui() { workaroundJavaFxInitializationBug(); - var messageBus = MessageBus.getMessageBus(); - //send before subscribing - messageBus.publishAsync(new TableModelChangeEvent(true, false)); - messageBus.subscribe(this); + subscribeTableModelChangeEvent(); SwingUtilities.invokeLater(() -> { if (Taskbar.isTaskbarSupported()) @@ -223,11 +220,7 @@ public MediathekGui() { checkInvalidRegularExpressions(); - logger.trace("Loading bandwidth monitor"); - if (config.getBoolean(ApplicationConfiguration.APPLICATION_UI_BANDWIDTH_MONITOR_VISIBLE, false)) { - showBandwidthUsageAction.actionPerformed(null); - } - logger.trace("Finished loading bandwidth monitor"); + loadBandwidthMonitor(); logger.trace("Loading info dialog"); filmInfo = new InfoDialog(this); @@ -267,6 +260,21 @@ public void onFailure(@NotNull Throwable t) { } } + private void loadBandwidthMonitor() { + logger.trace("Loading bandwidth monitor"); + if (config.getBoolean(ApplicationConfiguration.APPLICATION_UI_BANDWIDTH_MONITOR_VISIBLE, false)) { + showBandwidthUsageAction.actionPerformed(null); + } + logger.trace("Finished loading bandwidth monitor"); + } + + private void subscribeTableModelChangeEvent() { + var messageBus = MessageBus.getMessageBus(); + //send before subscribing + messageBus.publishAsync(new TableModelChangeEvent(true, false)); + messageBus.subscribe(this); + } + /** * Return the user interface instance * From d58a754d28cdf63f1b489ef5c62f1003b323bb64 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Fri, 22 Sep 2023 08:03:26 +0200 Subject: [PATCH 077/184] - change code behaviour for common pool termination --- .../java/mediathek/mainwindow/MediathekGui.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/mediathek/mainwindow/MediathekGui.java b/src/main/java/mediathek/mainwindow/MediathekGui.java index 00b3e028c6..ac9e612897 100644 --- a/src/main/java/mediathek/mainwindow/MediathekGui.java +++ b/src/main/java/mediathek/mainwindow/MediathekGui.java @@ -1169,14 +1169,13 @@ private void stopDownloads() { } private void waitForCommonPoolToComplete() { - while (ForkJoinPool.commonPool().hasQueuedSubmissions()) { - try { - logger.debug("POOL SUBMISSIONS: {}", ForkJoinPool.commonPool().getQueuedSubmissionCount()); - TimeUnit.MILLISECONDS.sleep(500); - } catch (InterruptedException ignored) { - } - } + var pool = ForkJoinPool.commonPool(); + boolean isQuiescent = pool.isQuiescent(); + while (pool.hasQueuedSubmissions() && !isQuiescent) { + logger.debug("POOL SUBMISSIONS: {}", pool.getQueuedSubmissionCount()); + isQuiescent = pool.awaitQuiescence(500, TimeUnit.MILLISECONDS); + } } /** From 5902ff127d0a910b08a2ba434d0f82e39fda6e12 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Mon, 9 Oct 2023 10:30:23 +0200 Subject: [PATCH 078/184] - upgrade JDK - refactor code for modern jlibnotify binding - bump library versions --- CHANGELOG.md | 4 +++- pom.xml | 10 +++++----- .../notification/LinuxNotificationCenter.java | 15 +++++++++------ 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2495bef27f..9a7e28b38d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # **14.0.1** -- JDK 20.0.2 wird nun mitgeliefert +- JDK 21 wird nun mitgeliefert. Behebt primär Darstellungsfehler von Java Apps unter Windows. - CVE in xerial-jdbc Bibliothek wurde durch eine neuere Version gefixt. +- **Linux:** Native notifications wurden für aktuelle Bibliotheksversion angepasst. - **BUGFIX:** Inkorrekte Beschreibung des "Gespeicherten Film abspielen" Toolbar-Button im Tab Download wurde korrigiert. - **BUGFIX:** Fehlendes Kontextmenü beim Suchfeld wurde hinzugefügt. - **BUGFIX:** Fehlendes Kontextmenü in der Filmbeschreibung zum Kopieren der URL wurde hinzugefügt. @@ -23,6 +24,7 @@ - **FEATURE:** Im *"Film speichern"*-Dialog können nun zur jeweils ausgewählten Qualitätsstufe ergänzende Filminformationen aus dem Netz geladen werden (Höhe x Breite, Bitrate). - **FEATURE(Linux):** Dark Mode Erkennung funktioniert nun auch mit GNOME. Danke an @swsnr! - **FEATURE(Linux):** Die Fensterdekorationen der Windows/macOS-Versionen werden nun auch unter Linux verwendet. + # **14.0.0** - Es wird nun Java 20 verwendet. - User Interface wurde primär für neue macOS-Versionen überarbeitet. diff --git a/pom.xml b/pom.xml index 1404353171..f6166b8825 100755 --- a/pom.xml +++ b/pom.xml @@ -80,8 +80,8 @@ UTF-8 - 20 - 20 + 21 + 21 20 1.9.0 ${jdk.language.version} @@ -117,7 +117,7 @@ 11.1 4.10.0 5.0.0-alpha.10 - 4.7.0 + 4.7.3 3.43.0.0 1.9 @@ -171,7 +171,7 @@ org.jfree jfreechart - 1.5.3 + 1.5.4 @@ -209,7 +209,7 @@ es.blackleg jlibnotify - 0.2.0 + 1.1.0 net.java.dev.jna diff --git a/src/main/java/mediathek/tool/notification/LinuxNotificationCenter.java b/src/main/java/mediathek/tool/notification/LinuxNotificationCenter.java index 75c0539080..a098da236d 100644 --- a/src/main/java/mediathek/tool/notification/LinuxNotificationCenter.java +++ b/src/main/java/mediathek/tool/notification/LinuxNotificationCenter.java @@ -1,7 +1,9 @@ package mediathek.tool.notification; -import es.blackleg.jlibnotify.LibNotify; -import es.blackleg.jlibnotify.core.DefaultLibNotifyLoader; +import es.blackleg.jlibnotify.JLibnotify; +import es.blackleg.jlibnotify.core.DefaultJLibnotifyLoader; +import es.blackleg.jlibnotify.exception.JLibnotifyInitException; +import es.blackleg.jlibnotify.exception.JLibnotifyLoadException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -9,12 +11,13 @@ public class LinuxNotificationCenter implements INotificationCenter, Closeable { private static final Logger logger = LogManager.getLogger(); - private LibNotify libNotify; + private JLibnotify libNotify; private boolean nativeSupport; public LinuxNotificationCenter() { try { - libNotify = DefaultLibNotifyLoader.getInstance().load(); + var loader = new DefaultJLibnotifyLoader(); + libNotify = loader.load(); libNotify.init("MediathekView"); nativeSupport = true; @@ -29,7 +32,7 @@ public LinuxNotificationCenter() { for (var s : caps) logger.debug("\t {}",s); } - catch (UnsatisfiedLinkError | RuntimeException e) { + catch (UnsatisfiedLinkError | RuntimeException | JLibnotifyLoadException | JLibnotifyInitException e) { nativeSupport = false; logger.error("failed to initialize libNotify",e); } @@ -38,7 +41,7 @@ public LinuxNotificationCenter() { @Override public void displayNotification(NotificationMessage msg) { var notification = libNotify.createNotification(msg.getTitle(), msg.message,"dialog-information"); - libNotify.showNotification(notification); + notification.show(); } public boolean hasNativeSupport() { From 3b78cdd6c81f5236b01c6a017dae87554be90d7e Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Tue, 17 Oct 2023 11:10:52 +0200 Subject: [PATCH 079/184] - implement selective download of missing file sizes --- CHANGELOG.md | 1 + .../gui/dialogEinstellungen/PanelDownload.java | 9 ++++++++- .../gui/dialogEinstellungen/PanelDownload.jfd | 10 ++++++++-- .../mediathek/tool/ApplicationConfiguration.java | 7 +++---- src/main/java/mediathek/tool/FileSize.java | 16 +++++++++++----- 5 files changed, 31 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a7e28b38d..a5357cb84b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ - **FEATURE:** Im *"Film speichern"*-Dialog können nun zur jeweils ausgewählten Qualitätsstufe ergänzende Filminformationen aus dem Netz geladen werden (Höhe x Breite, Bitrate). - **FEATURE(Linux):** Dark Mode Erkennung funktioniert nun auch mit GNOME. Danke an @swsnr! - **FEATURE(Linux):** Die Fensterdekorationen der Windows/macOS-Versionen werden nun auch unter Linux verwendet. +- **FEATURE:** Das Nachladen von fehlenden Filmgrößen kann in den Eistellungen abgeschaltet werden. # **14.0.0** - Es wird nun Java 20 verwendet. diff --git a/src/main/java/mediathek/gui/dialogEinstellungen/PanelDownload.java b/src/main/java/mediathek/gui/dialogEinstellungen/PanelDownload.java index 9ec7f08b26..ec724cb5b4 100644 --- a/src/main/java/mediathek/gui/dialogEinstellungen/PanelDownload.java +++ b/src/main/java/mediathek/gui/dialogEinstellungen/PanelDownload.java @@ -32,6 +32,7 @@ private void initComponents() { cbkDownloadError = new JCheckBox(); jCheckBoxBeep = new JCheckBox(); jButtonBeep = new JButton(); + cbFetchMissingFileSize = new JCheckBox(); //======== this ======== setLayout(new BorderLayout()); @@ -47,7 +48,8 @@ private void initComponents() { // rows new AC() .fill().gap() - .fill())); + .fill().gap() + )); //---- cbkDownloadError ---- cbkDownloadError.setText("Bei Downloadfehler eine Fehlermeldung anzeigen"); //NON-NLS @@ -60,6 +62,10 @@ private void initComponents() { //---- jButtonBeep ---- jButtonBeep.setText("Test"); //NON-NLS jPanel2.add(jButtonBeep, new CC().cell(1, 1)); + + //---- cbFetchMissingFileSize ---- + cbFetchMissingFileSize.setText("Fehlende Filmgr\u00f6\u00dfe nachladen"); //NON-NLS + jPanel2.add(cbFetchMissingFileSize, new CC().cell(0, 2)); } add(jPanel2, BorderLayout.CENTER); }// //GEN-END:initComponents @@ -70,5 +76,6 @@ private void initComponents() { private JCheckBox cbkDownloadError; private JCheckBox jCheckBoxBeep; private JButton jButtonBeep; + private JCheckBox cbFetchMissingFileSize; // End of variables declaration//GEN-END:variables } diff --git a/src/main/java/mediathek/gui/dialogEinstellungen/PanelDownload.jfd b/src/main/java/mediathek/gui/dialogEinstellungen/PanelDownload.jfd index d9e35b0331..2db9b7a9e3 100644 --- a/src/main/java/mediathek/gui/dialogEinstellungen/PanelDownload.jfd +++ b/src/main/java/mediathek/gui/dialogEinstellungen/PanelDownload.jfd @@ -1,4 +1,4 @@ -JFDML JFormDesigner: "7.0.2.4.305" Java: "11.0.7" encoding: "UTF-8" +JFDML JFormDesigner: "8.1.1.0.298" Java: "17.0.8.1" encoding: "UTF-8" new FormModel { contentType: "form/swing" @@ -8,7 +8,7 @@ new FormModel { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$layoutConstraints": "insets 5,hidemode 3,gap 5 5" "$columnConstraints": "[left][fill]" - "$rowConstraints": "[fill][fill]" + "$rowConstraints": "[fill][fill][]" } ) { name: "jPanel2" auxiliary() { @@ -32,6 +32,12 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 1 1" } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "cbFetchMissingFileSize" + "text": "Fehlende Filmgröße nachladen" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 2" + } ) }, new FormLayoutConstraints( class java.lang.String ) { "value": "Center" } ) diff --git a/src/main/java/mediathek/tool/ApplicationConfiguration.java b/src/main/java/mediathek/tool/ApplicationConfiguration.java index 790997266c..11a16c0548 100644 --- a/src/main/java/mediathek/tool/ApplicationConfiguration.java +++ b/src/main/java/mediathek/tool/ApplicationConfiguration.java @@ -63,6 +63,7 @@ public class ApplicationConfiguration { public static final String DOWNLOAD_SOUND_BEEP = "download.sound.beep"; public static final String DOWNLOAD_SHOW_DESCRIPTION = "download.show_description"; public static final String DOWNLOAD_MAX_SIMULTANEOUS_NUM = "download.max_simultaneous.number"; + public static final String DOWNLOAD_FETCH_FILE_SIZE = "download.fetch_file_size"; public static final String SEARCH_USE_FILM_DESCRIPTIONS = "searchfield.film.search_through_description"; public static final String FILM_SHOW_DESCRIPTION = "film.show_description"; @@ -120,8 +121,7 @@ public Country getGeographicLocation() { if (!str.startsWith("\"") && !str.endsWith("\"")) str = "\"" + str + "\""; return mapper.readValue(str, Country.class); - } - catch (Exception ex) { + } catch (Exception ex) { logger.error("Unable to parse country, resetting to GERMANY", ex); setGeographicLocation(Country.DE); return Country.DE; @@ -132,8 +132,7 @@ public void setGeographicLocation(Country country) { try { var newValue = mapper.writeValueAsString(country); config.setProperty(GEO_LOCATION, newValue); - } - catch (Exception ex) { + } catch (Exception ex) { logger.error("Error setting location, setting to GERMANY", ex); setGeographicLocation(Country.DE); } diff --git a/src/main/java/mediathek/tool/FileSize.java b/src/main/java/mediathek/tool/FileSize.java index 42aa90d2f4..57c5e96541 100644 --- a/src/main/java/mediathek/tool/FileSize.java +++ b/src/main/java/mediathek/tool/FileSize.java @@ -83,15 +83,21 @@ public static long getFileSizeFromUrl(@NotNull HttpUrl url) { return INVALID_SIZE; } - logger.info("Requesting file size for: {}", url); final Request request = new Request.Builder().url(url).head().build(); long respLength = INVALID_SIZE; - try (Response response = MVHttpClient.getInstance().getHttpClient().newCall(request).execute()) { - if (response.isSuccessful()) { - respLength = getContentLength(response); + + var fetchSize = ApplicationConfiguration.getConfiguration().getBoolean(ApplicationConfiguration.DOWNLOAD_FETCH_FILE_SIZE, true); + if (fetchSize) { + logger.info("Requesting file size for: {}", url); + try (Response response = MVHttpClient.getInstance().getHttpClient().newCall(request).execute()) { + if (response.isSuccessful()) { + respLength = getContentLength(response); + } + } catch (IOException ignored) { } - } catch (IOException ignored) { } + else + logger.info("Skipping file size request due to user setting"); if (respLength < ONE_MiB) { // alles unter 1MB sind Playlisten, ORF: Trailer bei im Ausland gesperrten Filmen, ... From 474748c38b44e06d963ce6ed7b44566352aa3828 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Tue, 17 Oct 2023 11:13:51 +0200 Subject: [PATCH 080/184] - fix typo and enhance description --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5357cb84b..214b190729 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,7 +24,7 @@ - **FEATURE:** Im *"Film speichern"*-Dialog können nun zur jeweils ausgewählten Qualitätsstufe ergänzende Filminformationen aus dem Netz geladen werden (Höhe x Breite, Bitrate). - **FEATURE(Linux):** Dark Mode Erkennung funktioniert nun auch mit GNOME. Danke an @swsnr! - **FEATURE(Linux):** Die Fensterdekorationen der Windows/macOS-Versionen werden nun auch unter Linux verwendet. -- **FEATURE:** Das Nachladen von fehlenden Filmgrößen kann in den Eistellungen abgeschaltet werden. +- **FEATURE:** Das Nachladen von fehlenden Filmgrößen kann in den *Einstellungen/Aufzeichnen und Abspielen/Download* abgeschaltet werden. # **14.0.0** - Es wird nun Java 20 verwendet. From 44a7d3d958e490d74b9f2d0c9a6ead7ff3adf0f2 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Tue, 17 Oct 2023 11:24:15 +0200 Subject: [PATCH 081/184] - add missing git merge data --- .../mediathek/gui/dialogEinstellungen/PanelDownload.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/mediathek/gui/dialogEinstellungen/PanelDownload.java b/src/main/java/mediathek/gui/dialogEinstellungen/PanelDownload.java index ec724cb5b4..fb46fd578b 100644 --- a/src/main/java/mediathek/gui/dialogEinstellungen/PanelDownload.java +++ b/src/main/java/mediathek/gui/dialogEinstellungen/PanelDownload.java @@ -10,7 +10,6 @@ import javax.swing.*; import java.awt.*; -@SuppressWarnings("serial") public class PanelDownload extends JPanel { public PanelDownload() { @@ -19,8 +18,12 @@ public PanelDownload() { cbkDownloadError.setSelected(Boolean.parseBoolean(MVConfig.get(MVConfig.Configs.SYSTEM_DOWNLOAD_ERRORMSG))); cbkDownloadError.addActionListener(e -> MVConfig.add(MVConfig.Configs.SYSTEM_DOWNLOAD_ERRORMSG, Boolean.toString(cbkDownloadError.isSelected()))); - jCheckBoxBeep.setSelected(ApplicationConfiguration.getConfiguration().getBoolean(ApplicationConfiguration.DOWNLOAD_SOUND_BEEP,false)); - jCheckBoxBeep.addActionListener(l -> ApplicationConfiguration.getConfiguration().setProperty(ApplicationConfiguration.DOWNLOAD_SOUND_BEEP,jCheckBoxBeep.isSelected())); + var config = ApplicationConfiguration.getConfiguration(); + jCheckBoxBeep.setSelected(config.getBoolean(ApplicationConfiguration.DOWNLOAD_SOUND_BEEP,false)); + jCheckBoxBeep.addActionListener(l -> config.setProperty(ApplicationConfiguration.DOWNLOAD_SOUND_BEEP,jCheckBoxBeep.isSelected())); + + cbFetchMissingFileSize.setSelected(config.getBoolean(ApplicationConfiguration.DOWNLOAD_FETCH_FILE_SIZE, true)); + cbFetchMissingFileSize.addActionListener(l -> config.setProperty(ApplicationConfiguration.DOWNLOAD_FETCH_FILE_SIZE, cbFetchMissingFileSize.isSelected())); jButtonBeep.addActionListener(ae -> Toolkit.getDefaultToolkit().beep()); } From dd2f3183e53e63c348283f0ce05411948b2d1695 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Tue, 17 Oct 2023 11:30:55 +0200 Subject: [PATCH 082/184] - add debug data to thread pool termination --- src/main/java/mediathek/mainwindow/MediathekGui.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/mediathek/mainwindow/MediathekGui.java b/src/main/java/mediathek/mainwindow/MediathekGui.java index ac9e612897..51a406b056 100644 --- a/src/main/java/mediathek/mainwindow/MediathekGui.java +++ b/src/main/java/mediathek/mainwindow/MediathekGui.java @@ -1141,19 +1141,23 @@ private void shutdownJavaFx() { } private void shutdownTimerPool() { + logger.trace("Entering shutdownTimerPool()"); + var timerPool = TimerPool.getTimerPool(); timerPool.shutdown(); try { if (!timerPool.awaitTermination(3, TimeUnit.SECONDS)) logger.warn("Time out occured before pool final termination"); } catch (InterruptedException e) { - logger.warn("timerPool shutdown exception", e); + logger.error("timerPool shutdown exception", e); } var taskList = timerPool.shutdownNow(); if (!taskList.isEmpty()) { logger.trace("timerPool taskList was not empty"); logger.trace(taskList.toString()); } + + logger.trace("Leaving shutdownTimerPool()"); } private void stopDownloads() { @@ -1169,13 +1173,17 @@ private void stopDownloads() { } private void waitForCommonPoolToComplete() { + logger.trace("Entering waitForCommonPoolToComplete()"); + var pool = ForkJoinPool.commonPool(); boolean isQuiescent = pool.isQuiescent(); while (pool.hasQueuedSubmissions() && !isQuiescent) { - logger.debug("POOL SUBMISSIONS: {}", pool.getQueuedSubmissionCount()); + logger.trace("POOL SUBMISSIONS: {}", pool.getQueuedSubmissionCount()); isQuiescent = pool.awaitQuiescence(500, TimeUnit.MILLISECONDS); } + + logger.trace("Entering waitForCommonPoolToComplete()"); } /** From 09b12b733cbf1b33a884d711bc95a7b6511c5a45 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Tue, 17 Oct 2023 11:31:18 +0200 Subject: [PATCH 083/184] - fix typo --- src/main/java/mediathek/mainwindow/MediathekGui.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/mediathek/mainwindow/MediathekGui.java b/src/main/java/mediathek/mainwindow/MediathekGui.java index 51a406b056..ea39ba76c5 100644 --- a/src/main/java/mediathek/mainwindow/MediathekGui.java +++ b/src/main/java/mediathek/mainwindow/MediathekGui.java @@ -1183,7 +1183,7 @@ private void waitForCommonPoolToComplete() { isQuiescent = pool.awaitQuiescence(500, TimeUnit.MILLISECONDS); } - logger.trace("Entering waitForCommonPoolToComplete()"); + logger.trace("Leaving waitForCommonPoolToComplete()"); } /** From d3fa8e9a0b4eea51c876cfd2de93b3fb269ea0eb Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Tue, 17 Oct 2023 14:46:40 +0200 Subject: [PATCH 084/184] - switch to Java 21 --- .github/workflows/build.yml | 4 ++-- .github/workflows/nightly.yml | 8 ++++---- .github/workflows/release.yml | 12 ++++++------ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 99725433b6..c66b3b661f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,11 +8,11 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up JDK 20 + - name: Set up JDK 21 uses: actions/setup-java@v2 with: distribution: 'zulu' - java-version: '20' + java-version: '21' java-package: jdk - name: Cache local Maven repository uses: actions/cache@v3 diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index d0d24478d6..67f4d713fd 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -18,11 +18,11 @@ jobs: id: check-if-changed with: paths: .github/workflows src/ res/ pom.xml .install4j/ .mvn/ - - name: Set up JDK 20 + - name: Set up JDK 21 if: steps.check-if-changed.outputs.changed == 'true' uses: actions/setup-java@v1 with: - java-version: 20 + java-version: 21 - name: Cache local Maven repository if: steps.check-if-changed.outputs.changed == 'true' @@ -73,10 +73,10 @@ jobs: - uses: actions/checkout@v2 with: ref: develop - - name: Set up JDK 20 + - name: Set up JDK 21 uses: actions/setup-java@v1 with: - java-version: 20 + java-version: 21 - uses: AdoptOpenJDK/install-jdk@v1 with: version: '8' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f525af69e3..1955c874e3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,11 +19,11 @@ jobs: id: check-if-changed with: paths: .github/workflows src/ res/ pom.xml .install4j/ .mvn/ - - name: Set up JDK 20 + - name: Set up JDK 21 if: steps.check-if-changed.outputs.changed == 'true' uses: actions/setup-java@v1 with: - java-version: 20 + java-version: 21 - name: Cache local Maven repository if: steps.check-if-changed.outputs.changed == 'true' @@ -74,11 +74,11 @@ jobs: - uses: actions/checkout@v2 with: ref: develop - - name: Set up JDK 20 + - name: Set up JDK 21 uses: actions/setup-java@v2 with: #distribution: 'temurin' - java-version: '20' + java-version: 21 - uses: AdoptOpenJDK/install-jdk@v1 with: version: '8' @@ -125,10 +125,10 @@ jobs: - uses: actions/checkout@v2 with: ref: develop - - name: Set up JDK 20 + - name: Set up JDK 21 uses: actions/setup-java@v1 with: - java-version: 20 + java-version: 21 - name: Get version run: echo "VERSION=$( ./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout )" >> $GITHUB_ENV - uses: actions/download-artifact@v2 From 6d7868cabe3577d1ea0d1f9472d8ddfba59da764 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Tue, 17 Oct 2023 14:56:20 +0200 Subject: [PATCH 085/184] - modernize setup-java action - use internal cache feature --- .github/workflows/build.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c66b3b661f..2956399497 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,18 +9,12 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up JDK 21 - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: distribution: 'zulu' java-version: '21' java-package: jdk - - name: Cache local Maven repository - uses: actions/cache@v3 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: | - ${{ runner.os }}-maven- + cache: 'maven' - name: Build and test with Maven run: ./mvnw -B package - name: SonarCloud Scan From 8237d94390da163b5f91b5b6bdbc60cd56e671e7 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Tue, 17 Oct 2023 15:33:06 +0200 Subject: [PATCH 086/184] - remove failed downloads automatically from seen history --- CHANGELOG.md | 1 + .../mediathek/controller/starter/DirectHttpDownload.java | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 214b190729..b8b8413b49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ - **FEATURE(Linux):** Dark Mode Erkennung funktioniert nun auch mit GNOME. Danke an @swsnr! - **FEATURE(Linux):** Die Fensterdekorationen der Windows/macOS-Versionen werden nun auch unter Linux verwendet. - **FEATURE:** Das Nachladen von fehlenden Filmgrößen kann in den *Einstellungen/Aufzeichnen und Abspielen/Download* abgeschaltet werden. +- **FEATURE:** Fehlerhafte Downloads werden nun automatisch aus der Gesehen Datenbank entfernt. # **14.0.0** - Es wird nun Java 20 verwendet. diff --git a/src/main/java/mediathek/controller/starter/DirectHttpDownload.java b/src/main/java/mediathek/controller/starter/DirectHttpDownload.java index efcc1f0365..12e5442c00 100644 --- a/src/main/java/mediathek/controller/starter/DirectHttpDownload.java +++ b/src/main/java/mediathek/controller/starter/DirectHttpDownload.java @@ -5,6 +5,7 @@ import mediathek.config.Konstanten; import mediathek.controller.MVBandwidthCountingInputStream; import mediathek.controller.ThrottlingInputStream; +import mediathek.controller.history.SeenHistoryController; import mediathek.daten.DatenDownload; import mediathek.gui.dialog.DialogContinueDownload; import mediathek.gui.dialog.MeldungDownloadfehler; @@ -257,6 +258,14 @@ private void downloadContent(InputStream inputStream) throws IOException { } else { //Anzeige ändern - bei Fehler fehlt der Eintrag start.status = Start.STATUS_ERR; + //in case of error remove seen indication + var film = datenDownload.film; + if (film != null) { + logger.trace("Removing errorneous download from history"); + try (var historyController = new SeenHistoryController()) { + historyController.markUnseen(film); + } + } } } } From 40e4525a9d817aad5fd9d749e44a192f1d851cb9 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Tue, 17 Oct 2023 15:52:31 +0200 Subject: [PATCH 087/184] - use github action caching for maven deps in nightly --- .github/workflows/nightly.yml | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 67f4d713fd..a47e73ba0c 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -20,18 +20,10 @@ jobs: paths: .github/workflows src/ res/ pom.xml .install4j/ .mvn/ - name: Set up JDK 21 if: steps.check-if-changed.outputs.changed == 'true' - uses: actions/setup-java@v1 + uses: actions/setup-java@v3 with: - java-version: 21 - - - name: Cache local Maven repository - if: steps.check-if-changed.outputs.changed == 'true' - uses: actions/cache@v2 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: | - ${{ runner.os }}-maven- + java-version: '21' + cache: 'maven' - name: Build and test with Maven if: steps.check-if-changed.outputs.changed == 'true' run: ./mvnw -B package @@ -74,9 +66,10 @@ jobs: with: ref: develop - name: Set up JDK 21 - uses: actions/setup-java@v1 + uses: actions/setup-java@v3 with: java-version: 21 + cache: 'maven' - uses: AdoptOpenJDK/install-jdk@v1 with: version: '8' @@ -89,13 +82,6 @@ jobs: - name: Extract install4j run: tar -zxvf install4j.tar.gz - - name: Cache local Maven repository - uses: actions/cache@v2 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: | - ${{ runner.os }}-maven- - name: Add install4j license run: ./mvnw clean install4j:install-license -Pinstall4j env: From 45adc5651297be26b5de2820a42ed239fab0b034 Mon Sep 17 00:00:00 2001 From: Christian F Date: Wed, 18 Oct 2023 06:25:35 +0200 Subject: [PATCH 088/184] Revert "- remove failed downloads automatically from seen history" This reverts commit 8237d94390da163b5f91b5b6bdbc60cd56e671e7. --- CHANGELOG.md | 1 - .../mediathek/controller/starter/DirectHttpDownload.java | 9 --------- 2 files changed, 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8b8413b49..214b190729 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,6 @@ - **FEATURE(Linux):** Dark Mode Erkennung funktioniert nun auch mit GNOME. Danke an @swsnr! - **FEATURE(Linux):** Die Fensterdekorationen der Windows/macOS-Versionen werden nun auch unter Linux verwendet. - **FEATURE:** Das Nachladen von fehlenden Filmgrößen kann in den *Einstellungen/Aufzeichnen und Abspielen/Download* abgeschaltet werden. -- **FEATURE:** Fehlerhafte Downloads werden nun automatisch aus der Gesehen Datenbank entfernt. # **14.0.0** - Es wird nun Java 20 verwendet. diff --git a/src/main/java/mediathek/controller/starter/DirectHttpDownload.java b/src/main/java/mediathek/controller/starter/DirectHttpDownload.java index 12e5442c00..efcc1f0365 100644 --- a/src/main/java/mediathek/controller/starter/DirectHttpDownload.java +++ b/src/main/java/mediathek/controller/starter/DirectHttpDownload.java @@ -5,7 +5,6 @@ import mediathek.config.Konstanten; import mediathek.controller.MVBandwidthCountingInputStream; import mediathek.controller.ThrottlingInputStream; -import mediathek.controller.history.SeenHistoryController; import mediathek.daten.DatenDownload; import mediathek.gui.dialog.DialogContinueDownload; import mediathek.gui.dialog.MeldungDownloadfehler; @@ -258,14 +257,6 @@ private void downloadContent(InputStream inputStream) throws IOException { } else { //Anzeige ändern - bei Fehler fehlt der Eintrag start.status = Start.STATUS_ERR; - //in case of error remove seen indication - var film = datenDownload.film; - if (film != null) { - logger.trace("Removing errorneous download from history"); - try (var historyController = new SeenHistoryController()) { - historyController.markUnseen(film); - } - } } } } From 95fc830e79bef7860425ad6c6b55795ff3fac030 Mon Sep 17 00:00:00 2001 From: Alexander Date: Wed, 18 Oct 2023 13:00:32 +0200 Subject: [PATCH 089/184] Update .gitlab-ci.yml Java Version auf 21 --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e47be8125c..27a43857c3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,7 +3,7 @@ variables: MAVEN_OPTS: "-Djava.awt.headless=true -Dmaven.repo.local=./.m2/repository" MAVEN_CLI_OPTS: "-B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn" -image: maven:3.9-eclipse-temurin-20 +image: maven:3.9-eclipse-temurin-21 cache: From 53e95a439237e401b013b777cb4c7619141c136a Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Wed, 18 Oct 2023 18:54:41 +0200 Subject: [PATCH 090/184] - remove failed downloads from history --- CHANGELOG.md | 3 ++- .../controller/starter/DirectHttpDownload.java | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 214b190729..1e9652cbf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,8 @@ - **FEATURE(Linux):** Dark Mode Erkennung funktioniert nun auch mit GNOME. Danke an @swsnr! - **FEATURE(Linux):** Die Fensterdekorationen der Windows/macOS-Versionen werden nun auch unter Linux verwendet. - **FEATURE:** Das Nachladen von fehlenden Filmgrößen kann in den *Einstellungen/Aufzeichnen und Abspielen/Download* abgeschaltet werden. - +- **FEATURE:** Fehlerhafte Downloads werden nun automatisch aus der Gesehen Datenbank entfernt. +- # **14.0.0** - Es wird nun Java 20 verwendet. - User Interface wurde primär für neue macOS-Versionen überarbeitet. diff --git a/src/main/java/mediathek/controller/starter/DirectHttpDownload.java b/src/main/java/mediathek/controller/starter/DirectHttpDownload.java index efcc1f0365..edf492fa69 100644 --- a/src/main/java/mediathek/controller/starter/DirectHttpDownload.java +++ b/src/main/java/mediathek/controller/starter/DirectHttpDownload.java @@ -5,6 +5,7 @@ import mediathek.config.Konstanten; import mediathek.controller.MVBandwidthCountingInputStream; import mediathek.controller.ThrottlingInputStream; +import mediathek.controller.history.SeenHistoryController; import mediathek.daten.DatenDownload; import mediathek.gui.dialog.DialogContinueDownload; import mediathek.gui.dialog.MeldungDownloadfehler; @@ -340,6 +341,9 @@ public synchronized void run() { logger.error("run()", ex); start.status = Start.STATUS_ERR; state = HttpDownloadState.ERROR; + + removeSeenHistoryEntry(); + SwingUtilities.invokeLater(() -> new MeldungDownloadfehler(MediathekGui.ui(), ex.getLocalizedMessage(), datenDownload).setVisible(true)); } finally { if (body != null) @@ -357,6 +361,15 @@ public synchronized void run() { messageBus.unsubscribe(this); } + private void removeSeenHistoryEntry() { + if (datenDownload.film != null) { + logger.trace("Removing failed download entry from history"); + try (var historyController = new SeenHistoryController()) { + historyController.markUnseen(datenDownload.film); + } + } + } + private void waitForPendingDownloads() { try { if (infoFuture != null) From 47d009574ee10a6ae424b5f996f680f6020dd163 Mon Sep 17 00:00:00 2001 From: derreisende77 Date: Wed, 18 Oct 2023 20:10:34 +0200 Subject: [PATCH 091/184] Update lucene_help.md --- lucene_help.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lucene_help.md b/lucene_help.md index 63df0d0ebe..5eebeee2fd 100644 --- a/lucene_help.md +++ b/lucene_help.md @@ -1,5 +1,7 @@ MediathekView verwendet im **Experten-Modus** zur Suche nach Filmtiteln nun die Volltextsuche [Apache Lucene](https://lucene.apache.org). Damit einhergehend kann die bisher verwendete Suchfunktionalität nicht mehr genutzt werden, jedoch erschließen sich durch die neu integrierte professionelle Suche viel mehr Möglichkeiten, die Ergebnisse einzugrenzen. +**Wird im Suchfeld nur Text ohne ein unten aufgeführtes Tag eingegeben, ist gds. das Tag `titel` der Suchbereich.** + MediathekView bietet die folgenden *tags* für die Formulierung von Suchabfragen an: | Name | Typ | Beschreibung | @@ -24,4 +26,4 @@ Es ist nicht möglich, Filme anhand von URLs bzw. Teilsegmenten davon zu suchen. Um sich mit der Abfragesyntax vertraut zu machen sind nachfolgende Links empfohlen: 1. [Lucene Query Syntax](https://ci-builds.apache.org/job/Lucene/job/Lucene-Artifacts-main/javadoc/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#package.description) -2. [Lucene Tutorial](http://lucenetutorial.com/lucene-query-syntax.html) \ No newline at end of file +2. [Lucene Tutorial](http://lucenetutorial.com/lucene-query-syntax.html) From f42537ff8cb05cd7c9b2ccc5b810bae44f84e856 Mon Sep 17 00:00:00 2001 From: derreisende77 Date: Wed, 18 Oct 2023 20:47:56 +0200 Subject: [PATCH 092/184] Update lucene_help.md --- lucene_help.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lucene_help.md b/lucene_help.md index 5eebeee2fd..ec8e7764a8 100644 --- a/lucene_help.md +++ b/lucene_help.md @@ -2,7 +2,7 @@ MediathekView verwendet im **Experten-Modus** zur Suche nach Filmtiteln nun die **Wird im Suchfeld nur Text ohne ein unten aufgeführtes Tag eingegeben, ist gds. das Tag `titel` der Suchbereich.** -MediathekView bietet die folgenden *tags* für die Formulierung von Suchabfragen an: +MediathekView bietet die folgenden *tags* (Achtung: hier sind **immer** Kleinbuchstaben zu verwenden) für die Formulierung von Suchabfragen an: | Name | Typ | Beschreibung | | ------------- | ------- | ------------------------------------------------------------ | From 87e81a6a76d6fdebea0bb908a1eb2009e7c43843 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Sun, 22 Oct 2023 22:18:29 +0200 Subject: [PATCH 093/184] - upgrade install4j JDK to 21 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f6166b8825..cf80be755d 100755 --- a/pom.xml +++ b/pom.xml @@ -124,8 +124,8 @@ mediathek.Main - 20/20.0.2 - 20 + 21/21.0.1 + 21 -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact -XX:MaxRAMPercentage=50.0 From 35f3d40930d1a6f3b91ac45da4e5320d3079e108 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Tue, 24 Oct 2023 11:03:43 +0200 Subject: [PATCH 094/184] - bump library versions --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index cf80be755d..f729c2cd06 100755 --- a/pom.xml +++ b/pom.xml @@ -93,7 +93,7 @@ 2.11.0 3.12.0 11.1.2 - 3.2.1 + 3.2.5 32.1.2-jre 1.1.2 2.15.2 @@ -101,7 +101,7 @@ 20.0.1 1.3 5.13.0 - 5.9.0 + 5.9.2 2.20.0 3.3.0 3.1.0 @@ -115,7 +115,7 @@ 3.2.1 3.0.0-M5 11.1 - 4.10.0 + 5.2.0 5.0.0-alpha.10 4.7.3 3.43.0.0 From a9b8093b7e8487082d3398b6f750e03145344492 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Wed, 25 Oct 2023 23:54:33 +0200 Subject: [PATCH 095/184] - QUICK FIX for macOS Sonoma 14.1 freezes!!! - disable restore of memory monitor dialog - do not try to cleanup hidden JavaFX window --- .../java/mediathek/mainwindow/MediathekGui.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/mediathek/mainwindow/MediathekGui.java b/src/main/java/mediathek/mainwindow/MediathekGui.java index ea39ba76c5..6066dda0d8 100644 --- a/src/main/java/mediathek/mainwindow/MediathekGui.java +++ b/src/main/java/mediathek/mainwindow/MediathekGui.java @@ -513,8 +513,12 @@ protected void workaroundJavaFxInitializationBug() { private void createMemoryMonitor() { boolean visible = ApplicationConfiguration.getConfiguration().getBoolean(ApplicationConfiguration.MemoryMonitorDialog.VISIBLE, false); - if (visible) - showMemoryMonitorAction.showMemoryMonitor(); + if (visible) { + if (!SystemUtils.IS_OS_MAC_OSX) { + //FIXME macOS Sonoma 14.1 causes freeze when showing on startup... + showMemoryMonitorAction.showMemoryMonitor(); + } + } } /** @@ -1136,7 +1140,10 @@ private void cleanupLuceneIndex() { * Gracefully shutdown the JavaFX environment. */ private void shutdownJavaFx() { - JavaFxUtils.invokeInFxThreadAndWait(() -> JFXHiddenApplication.getPrimaryStage().close()); + //FIXME macOS Sonoma 14.1 causes freezes here :-( + if (!SystemUtils.IS_OS_MAC_OSX) + JavaFxUtils.invokeInFxThreadAndWait(() -> JFXHiddenApplication.getPrimaryStage().close()); + Platform.exit(); } From cc045fa0db739612f27a9e8e50ace1646de26d4d Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Thu, 26 Oct 2023 13:20:12 +0200 Subject: [PATCH 096/184] - First changes to fix/workaround multiple hangs on macOS Sonoma 14.1 - disable shutdown progress dialog when quitting app as it does not work on macOS Sonoma 14.1 - bump library version --- CHANGELOG.md | 5 +- pom.xml | 2 +- .../gui/actions/MemoryMonitorAction.java | 1 + .../javafx/tool/JFXHiddenApplication.java | 9 -- .../mediathek/mainwindow/MediathekGui.java | 70 ++++++------ .../mainwindow/MemoryUsagePanel.java | 15 --- .../mainwindow/ShutdownDialogController.kt | 44 -------- .../tool/ApplicationConfiguration.java | 6 +- .../java/mediathek/tool/DarkModeDetector.java | 106 ------------------ .../mediathek/tool/RuntimeStatistics.java | 13 +-- .../java/mediathek/tool/ShutdownState.java | 26 ----- 11 files changed, 52 insertions(+), 245 deletions(-) delete mode 100644 src/main/java/mediathek/mainwindow/ShutdownDialogController.kt delete mode 100644 src/main/java/mediathek/tool/ShutdownState.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e9652cbf8..2c5f8df5a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,10 @@ - **FEATURE:** Fehlerhafte Downloads werden nun automatisch aus der Gesehen Datenbank entfernt. - # **14.0.0** -- Es wird nun Java 20 verwendet. +- **ACHTUNG: macOS Sonoma 14.1 verursacht diverse Probleme und Programmhänger! Einige dieser Probleme konnten beseitigt werden, führen aber zu kleineren Einschränkungen.** +- macOS: Speicherverbrauchsanzeige wurde deaktiviert. Sie verursacht bisher unbekannte Programmanomalien unter macOS Sonoma 14.1 +- Beim Beenden wird kein Fortschrittsdialog mehr angezeigt. +- Es wird nun Java 21 verwendet. - User Interface wurde primär für neue macOS-Versionen überarbeitet. - Die *macOS Intel* Version nutzt nun Liberica JDK full mit integriertem JavaFX. Dadurch kann MediathekView nun auch wieder fehlerfrei mit Apple Silicon Macs gebaut werden. - Das Programm überprüft beim Start ob die JVM-Parameter korrekt sind und gibt ansonsten eine Warnung aus. Dies kann über die Paramter `-nj` oder `--no-jvm-param-checks` deaktiviert werden. diff --git a/pom.xml b/pom.xml index f729c2cd06..b276f59ebb 100755 --- a/pom.xml +++ b/pom.xml @@ -98,7 +98,7 @@ 1.1.2 2.15.2 2022.06.03 - 20.0.1 + 21.0.1 1.3 5.13.0 5.9.2 diff --git a/src/main/java/mediathek/gui/actions/MemoryMonitorAction.java b/src/main/java/mediathek/gui/actions/MemoryMonitorAction.java index a45cacb4af..1b88fd952d 100644 --- a/src/main/java/mediathek/gui/actions/MemoryMonitorAction.java +++ b/src/main/java/mediathek/gui/actions/MemoryMonitorAction.java @@ -18,6 +18,7 @@ public MemoryMonitorAction(@NotNull JFrame parent) { public void closeMemoryMonitor() { if (dialog != null) { dialog.dispose(); + dialog = null; } } diff --git a/src/main/java/mediathek/javafx/tool/JFXHiddenApplication.java b/src/main/java/mediathek/javafx/tool/JFXHiddenApplication.java index 2f5a2b613a..53aa785ba9 100644 --- a/src/main/java/mediathek/javafx/tool/JFXHiddenApplication.java +++ b/src/main/java/mediathek/javafx/tool/JFXHiddenApplication.java @@ -2,7 +2,6 @@ import javafx.application.Application; import javafx.scene.Scene; -import javafx.scene.image.Image; import javafx.scene.layout.Pane; import javafx.stage.Stage; import javafx.stage.StageStyle; @@ -10,17 +9,10 @@ public class JFXHiddenApplication extends Application { private static Stage primaryStage; - private static final String ICON_NAME = "MediathekView.png"; - private static final String ICON_PATH = "/mediathek/res/"; - public static void launchApplication() { new Thread(JFXHiddenApplication::launch).start(); } - public static Image getApplicationImage() { - return new Image(JFXHiddenApplication.class.getResourceAsStream(ICON_PATH + ICON_NAME)); - } - @Override public void start(Stage primaryStage) { JFXHiddenApplication.primaryStage = primaryStage; @@ -30,7 +22,6 @@ public void start(Stage primaryStage) { primaryStage.setTitle("MediathekView Invisible Helper Window"); - primaryStage.getIcons().add(getApplicationImage()); primaryStage.show(); primaryStage.hide(); } diff --git a/src/main/java/mediathek/mainwindow/MediathekGui.java b/src/main/java/mediathek/mainwindow/MediathekGui.java index 6066dda0d8..63d9bb1e3f 100644 --- a/src/main/java/mediathek/mainwindow/MediathekGui.java +++ b/src/main/java/mediathek/mainwindow/MediathekGui.java @@ -909,7 +909,15 @@ private void createFileMenu() { private void createViewMenu() { jMenuAnsicht.addSeparator(); - jMenuAnsicht.add(showMemoryMonitorAction); + if (!SystemUtils.IS_OS_MAC_OSX) { + jMenuAnsicht.add(showMemoryMonitorAction); + } + else { + // only show for debug purposes...wil cause hang at shutdown + if (Config.isDebugModeEnabled()) { + jMenuAnsicht.add(showMemoryMonitorAction); + } + } jMenuAnsicht.add(showBandwidthUsageAction); jMenuAnsicht.addSeparator(); jMenuAnsicht.add(tabFilme.toggleFilterDialogVisibilityAction); @@ -1036,6 +1044,8 @@ public boolean quitApplication(boolean shouldDownloadAndQuit) { setShutdownRequested(dialogBeenden.isShutdownRequested()); } + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + if (automaticFilmlistUpdate != null) automaticFilmlistUpdate.close(); @@ -1051,71 +1061,64 @@ public boolean quitApplication(boolean shouldDownloadAndQuit) { manageAboAction.closeDialog(); - ShutdownDialogController shutdownProgress = new ShutdownDialogController(this); - shutdownProgress.show(); - - var historyWorker = CompletableFuture.runAsync(() -> { - try (SeenHistoryController history = new SeenHistoryController()) { - history.performMaintenance(); - } - }); + logger.info("Perform history maintenance."); + try (SeenHistoryController history = new SeenHistoryController()) { + history.performMaintenance(); + } - var bookmarkWorker = CompletableFuture.runAsync(() -> - daten.getListeBookmarkList().saveToFile(StandardLocations.getBookmarkFilePath())); + logger.info("Save bookmark list."); + daten.getListeBookmarkList().saveToFile(StandardLocations.getBookmarkFilePath()); // stop the download thread - shutdownProgress.setStatus(ShutdownState.TERMINATE_STARTER_THREAD); + logger.info("Stop Starter Thread."); daten.getStarterClass().getStarterThread().interrupt(); - shutdownProgress.setStatus(ShutdownState.SHUTDOWN_NOTIFICATION_CENTER); + logger.info("Close Notification center."); closeNotificationCenter(); // Tabelleneinstellungen merken - shutdownProgress.setStatus(ShutdownState.SAVE_FILM_DATA); + logger.info("Save Tab Filme data."); tabFilme.tabelleSpeichern(); tabFilme.saveSettings(); // needs thread pools active! tabFilme.filmActionPanel.getFilterDialog().dispose(); - shutdownProgress.setStatus(ShutdownState.SAVE_DOWNLOAD_DATA); + logger.info("Save Tab Download data."); tabDownloads.tabelleSpeichern(); - shutdownProgress.setStatus(ShutdownState.STOP_DOWNLOADS); + logger.info("Stop all downloads."); stopDownloads(); - shutdownProgress.setStatus(ShutdownState.SAVE_APP_DATA); + logger.info("Save app data."); daten.allesSpeichern(); - shutdownProgress.setStatus(ShutdownState.SHUTDOWN_THREAD_POOL); + logger.info("Shutdown pools."); shutdownTimerPool(); waitForCommonPoolToComplete(); //shutdown JavaFX - shutdownProgress.setStatus(ShutdownState.TERMINATE_JAVAFX_SUPPORT); + logger.info("Shutdown JavaFX."); shutdownJavaFx(); - try { - shutdownProgress.setStatus(ShutdownState.SAVE_BOOKMARKS); - bookmarkWorker.get(); - - shutdownProgress.setStatus(ShutdownState.PERFORM_SEEN_HISTORY_MAINTENANCE); - historyWorker.get(); - } catch (InterruptedException | ExecutionException e) { - logger.error("Async task error", e); - } - //close main window + logger.info("Close main window."); dispose(); //write all settings if not done already... + logger.info("Write app config."); ApplicationConfiguration.getInstance().writeConfiguration(); RuntimeStatistics.printRuntimeStatistics(); - RuntimeStatistics.printDataUsageStatistics(); - shutdownProgress.setStatus(ShutdownState.COMPLETE); + if (Config.isEnhancedLoggingEnabled()) { + RuntimeStatistics.printDataUsageStatistics(); + } + logger.info("Cleanup Lucene index."); cleanupLuceneIndex(); + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + if (isShutdownRequested()) { + logger.info("Requesting computer shutdown."); shutdownComputer(); } @@ -1140,9 +1143,10 @@ private void cleanupLuceneIndex() { * Gracefully shutdown the JavaFX environment. */ private void shutdownJavaFx() { - //FIXME macOS Sonoma 14.1 causes freezes here :-( - if (!SystemUtils.IS_OS_MAC_OSX) + //causes system hang on Sonoma 14.1 + if (!SystemUtils.IS_OS_MAC_OSX) { JavaFxUtils.invokeInFxThreadAndWait(() -> JFXHiddenApplication.getPrimaryStage().close()); + } Platform.exit(); } diff --git a/src/main/java/mediathek/mainwindow/MemoryUsagePanel.java b/src/main/java/mediathek/mainwindow/MemoryUsagePanel.java index e566390338..c5cec368ee 100644 --- a/src/main/java/mediathek/mainwindow/MemoryUsagePanel.java +++ b/src/main/java/mediathek/mainwindow/MemoryUsagePanel.java @@ -4,8 +4,6 @@ import mediathek.tool.MessageBus; import net.engio.mbassy.listener.Handler; import org.jetbrains.annotations.NotNull; -import org.jfree.chart.ChartMouseEvent; -import org.jfree.chart.ChartMouseListener; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.DateAxis; @@ -64,7 +62,6 @@ public MemoryUsagePanel(int maxAge, @NotNull TimeUnit timeUnit) { var chart = new JFreeChart(plot); chart.removeLegend(); var chartPanel = new ChartPanel(chart); - chartPanel.addChartMouseListener(new GarbageCollectionMouseListener()); chartPanel.setPopupMenu(null); add(chartPanel); @@ -92,18 +89,6 @@ private void addTotalObservation(double y) { total.add(new Millisecond(), y); } - private static class GarbageCollectionMouseListener implements ChartMouseListener { - @Override - public void chartMouseClicked(ChartMouseEvent event) { - System.gc(); - } - - @Override - public void chartMouseMoved(ChartMouseEvent event) { - - } - } - public class MemoryUsageDataGenerator extends Timer implements ActionListener { /** diff --git a/src/main/java/mediathek/mainwindow/ShutdownDialogController.kt b/src/main/java/mediathek/mainwindow/ShutdownDialogController.kt deleted file mode 100644 index 6b2c5bbb1e..0000000000 --- a/src/main/java/mediathek/mainwindow/ShutdownDialogController.kt +++ /dev/null @@ -1,44 +0,0 @@ -package mediathek.mainwindow - -import mediathek.gui.AppShutdownWindow -import mediathek.tool.ShutdownState -import java.util.* -import java.util.concurrent.TimeUnit - -/** - * Display a wait dialog with some status message to inform user what is happening currently. - */ -class ShutdownDialogController(private val gui: MediathekGui) { - private val window: AppShutdownWindow = AppShutdownWindow(gui) - private var curSteps = 0.0 - - init { - window.progress.maximum = EnumSet.allOf(ShutdownState::class.java).size - } - - fun show() { - gui.isEnabled = false - window.label1.isBusy = true - window.isVisible = true - } - - fun setStatus(state: ShutdownState) { - curSteps++ - window.message.text = state.toString() - window.message.paintImmediately(0, 0, window.message.width, window.message.height) - window.progress.value = curSteps.toInt() - window.progress.paintImmediately(0, 0, window.progress.width, window.progress.height) - window.label1.paintImmediately(0, 0, window.label1.width, window.label1.height) - /*try { - TimeUnit.MILLISECONDS.sleep(750) - } - catch (ignored: InterruptedException) {}*/ - if (state == ShutdownState.COMPLETE) { - try { - TimeUnit.MILLISECONDS.sleep(500) - window.dispose() - } catch (ignored: InterruptedException) { - } - } - } -} \ No newline at end of file diff --git a/src/main/java/mediathek/tool/ApplicationConfiguration.java b/src/main/java/mediathek/tool/ApplicationConfiguration.java index 11a16c0548..c54029c01d 100644 --- a/src/main/java/mediathek/tool/ApplicationConfiguration.java +++ b/src/main/java/mediathek/tool/ApplicationConfiguration.java @@ -80,6 +80,7 @@ public class ApplicationConfiguration { * A custom small thread scheduler exclusively for config changes. */ private final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2); + private final TimerTaskListener timerTaskListener = new TimerTaskListener(); private XMLConfiguration config; private FileHandler handler; /** @@ -147,7 +148,7 @@ public void setBlacklistDoNotShowGeoblockedFilms(boolean newValue) { } private void initializeTimedEventWriting() { - config.addEventListener(ConfigurationEvent.ANY, new TimerTaskListener()); + config.addEventListener(ConfigurationEvent.ANY, timerTaskListener); } private void setupXmlConfiguration() { @@ -179,7 +180,8 @@ private void loadOrCreateConfiguration() { public void writeConfiguration() { try { // cancel a pending writer task first - if (future != null) future.cancel(false); + config.removeEventListener(ConfigurationEvent.ANY, timerTaskListener); + if (future != null) future.cancel(true); handler.save(); } catch (ConfigurationException configurationException) { diff --git a/src/main/java/mediathek/tool/DarkModeDetector.java b/src/main/java/mediathek/tool/DarkModeDetector.java index bf41eb40cd..31d0de6af1 100644 --- a/src/main/java/mediathek/tool/DarkModeDetector.java +++ b/src/main/java/mediathek/tool/DarkModeDetector.java @@ -1,12 +1,8 @@ package mediathek.tool; -import javafx.scene.paint.Color; import org.apache.commons.lang3.SystemUtils; import java.io.*; -import java.util.Arrays; -import java.util.List; -import java.util.Map; import java.util.concurrent.TimeUnit; @@ -15,14 +11,6 @@ * Based on java code from this gist. */ public class DarkModeDetector { - public static final Map MACOS_ACCENT_COLOR_MAP = Map.of(-1, new Color[] { MacOSSystemColor.GRAY.colorAqua, MacOSSystemColor.GRAY.colorDark }, - 0, new Color[] { MacOSSystemColor.RED.colorAqua, MacOSSystemColor.RED.colorDark }, - 1, new Color[] { MacOSSystemColor.ORANGE.colorAqua, MacOSSystemColor.ORANGE.colorDark }, - 2, new Color[] { MacOSSystemColor.YELLOW.colorAqua, MacOSSystemColor.YELLOW.colorDark }, - 3, new Color[] { MacOSSystemColor.GREEN.colorAqua, MacOSSystemColor.GREEN.colorDark }, - 4, new Color[] { MacOSSystemColor.BLUE.colorAqua, MacOSSystemColor.BLUE.colorDark }, - 5, new Color[] { MacOSSystemColor.PURPLE.colorAqua, MacOSSystemColor.PURPLE.colorDark }, - 6, new Color[] { MacOSSystemColor.PINK.colorAqua, MacOSSystemColor.PINK.colorDark }); private static final String REGQUERY_UTIL = "reg query "; private static final String REGDWORD_TOKEN = "REG_DWORD"; private static final String DARK_THEME_CMD = REGQUERY_UTIL + "\"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize\"" + " /v AppsUseLightTheme"; @@ -125,100 +113,6 @@ private static boolean isWindowsDarkMode() { } } - public static Color getMacOSAccentColor() { - if (SystemUtils.IS_OS_MAC_OSX) - return MacOSAccentColor.MULTI_COLOR.getColorAqua(); - - final boolean isDarkMode = isMacOsDarkMode(); - try { - Integer colorKey = null; - Runtime runtime = Runtime.getRuntime(); - Process process = runtime.exec(new String[]{"defaults", "read", "-g", "AppleAccentColor"}); - InputStreamReader isr = new InputStreamReader(process.getInputStream()); - BufferedReader rdr = new BufferedReader(isr); - String line; - while((line = rdr.readLine()) != null) { - colorKey = Integer.valueOf(line); - } - int rc = process.waitFor(); // Wait for the process to complete - if (0 == rc) { - return isDarkMode ? MACOS_ACCENT_COLOR_MAP.get(colorKey)[1] : MACOS_ACCENT_COLOR_MAP.get(colorKey)[0]; - } else { - return isDarkMode ? MACOS_ACCENT_COLOR_MAP.get(4)[1] : MACOS_ACCENT_COLOR_MAP.get(4)[0]; - } - } catch (IOException | InterruptedException e) { - return isDarkMode ? MACOS_ACCENT_COLOR_MAP.get(4)[1] : MACOS_ACCENT_COLOR_MAP.get(4)[0]; - } - } - - public enum MacOSSystemColor { - BLUE(Color.rgb(0, 122, 255), Color.rgb(10, 132, 255)), - BROWN(Color.rgb(162, 132, 94), Color.rgb(172, 142, 104)), - GRAY(Color.rgb(142, 142, 147), Color.rgb(152, 152, 157)), - GREEN(Color.rgb(40, 205, 65), Color.rgb(50, 215, 75)), - INIDIGO(Color.rgb(88, 86, 214), Color.rgb(94, 92, 230)), - ORANGE(Color.rgb(255, 149, 0), Color.rgb(255, 159, 0)), - PINK(Color.rgb(255, 45, 85), Color.rgb(255, 55, 95)), - PURPLE(Color.rgb(175, 82, 222), Color.rgb(191, 90, 242)), - RED(Color.rgb(255, 59, 48), Color.rgb(255, 69, 58)), - TEAL(Color.rgb(85, 190, 240), Color.rgb(90, 200, 245)), - YELLOW(Color.rgb(255, 204, 0), Color.rgb(255, 214, 10)); - - final Color colorAqua; - final Color colorDark; - - - MacOSSystemColor(final Color colorAqua, final Color colorDark) { - this.colorAqua = colorAqua; - this.colorDark = colorDark; - } - - public static List getAsList() { return Arrays.asList(values()); } - - public Color getColorAqua() { return colorAqua; } - - public Color getColorDark() { return colorDark; } - - public boolean isGivenColor(final Color color) { - return (colorAqua.equals(color) || colorDark.equals(color)); - } - } - - public enum MacOSAccentColor { - MULTI_COLOR(null, MacOSSystemColor.BLUE.colorAqua, MacOSSystemColor.BLUE.colorDark), - GRAPHITE(-1, MacOSSystemColor.GRAY.colorAqua, MacOSSystemColor.GRAY.colorDark), - RED(0, MacOSSystemColor.RED.colorAqua, MacOSSystemColor.RED.colorDark), - ORANGE(1, MacOSSystemColor.ORANGE.colorAqua, MacOSSystemColor.ORANGE.colorDark), - YELLOW(2, MacOSSystemColor.YELLOW.colorAqua, MacOSSystemColor.YELLOW.colorDark), - GREEN(3, MacOSSystemColor.GREEN.colorAqua, MacOSSystemColor.GREEN.colorDark), - BLUE(4, MacOSSystemColor.BLUE.colorAqua, MacOSSystemColor.BLUE.colorDark), - PURPLE(5, MacOSSystemColor.PURPLE.colorAqua, MacOSSystemColor.PURPLE.colorDark), - PINK(6, MacOSSystemColor.PINK.colorAqua, MacOSSystemColor.PINK.colorDark); - - final Integer key; - final Color colorAqua; - final Color colorDark; - - - MacOSAccentColor(final Integer key, final Color colorAqua, final Color colorDark) { - this.key = key; - this.colorAqua = colorAqua; - this.colorDark = colorDark; - } - - public static List getAsList() { return Arrays.asList(values()); } - - public Integer getKey() { return key; } - - public Color getColorAqua() { return colorAqua; } - - public Color getColorDark() { return colorDark; } - - public boolean isGivenColor(final Color color) { - return (colorAqua.equals(color) || colorDark.equals(color)); - } - } - // ******************** Internal Classes ********************************** static class StreamReader extends Thread { private final InputStream is; diff --git a/src/main/java/mediathek/tool/RuntimeStatistics.java b/src/main/java/mediathek/tool/RuntimeStatistics.java index 9371e0e74a..f22e04f569 100644 --- a/src/main/java/mediathek/tool/RuntimeStatistics.java +++ b/src/main/java/mediathek/tool/RuntimeStatistics.java @@ -1,6 +1,5 @@ package mediathek.tool; -import mediathek.config.Config; import mediathek.tool.http.MVHttpClient; import org.apache.logging.log4j.LogManager; @@ -19,7 +18,7 @@ public class RuntimeStatistics { public static void printRuntimeStatistics() { DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; final var endZeit = LocalDateTime.now(); - final var runTime = LocalTime.MIN.plusSeconds(Duration.between(startZeit,endZeit).toSeconds()); + final var runTime = LocalTime.MIN.plusSeconds(Duration.between(startZeit, endZeit).toSeconds()); var logger = LogManager.getLogger(); logger.info("################################################################################"); @@ -29,11 +28,9 @@ public static void printRuntimeStatistics() { } public static void printDataUsageStatistics() { - if (Config.isEnhancedLoggingEnabled()) { - var byteCounter = MVHttpClient.getInstance().getByteCounter(); - var logger = LogManager.getLogger(); - logger.info("total data sent: {}", FileUtils.humanReadableByteCountBinary(byteCounter.totalBytesWritten())); - logger.info("total data received: {}", FileUtils.humanReadableByteCountBinary(byteCounter.totalBytesRead())); - } + var byteCounter = MVHttpClient.getInstance().getByteCounter(); + var logger = LogManager.getLogger(); + logger.info("total data sent: {}", FileUtils.humanReadableByteCountBinary(byteCounter.totalBytesWritten())); + logger.info("total data received: {}", FileUtils.humanReadableByteCountBinary(byteCounter.totalBytesRead())); } } diff --git a/src/main/java/mediathek/tool/ShutdownState.java b/src/main/java/mediathek/tool/ShutdownState.java deleted file mode 100644 index f2af880aba..0000000000 --- a/src/main/java/mediathek/tool/ShutdownState.java +++ /dev/null @@ -1,26 +0,0 @@ -package mediathek.tool; - -public enum ShutdownState { - TERMINATE_STARTER_THREAD("Downloadthread beenden..."), - SHUTDOWN_NOTIFICATION_CENTER("Native Benachrichtigungen beenden..."), - SHUTDOWN_THREAD_POOL("Beende Threadpools..."), - PERFORM_SEEN_HISTORY_MAINTENANCE("Führe Wartung an der Download-Historie durch..."), - SAVE_FILM_DATA("Film-Daten sichern"), - SAVE_DOWNLOAD_DATA("Download-Daten sichern"), - STOP_DOWNLOADS("Downloads anhalten"), - SAVE_APP_DATA("Programmdaten sichern"), - SAVE_BOOKMARKS("Merkliste sichern"), - - TERMINATE_JAVAFX_SUPPORT("Beende JavaFX Support..."), - COMPLETE("Fertig."); - private final String title; - - ShutdownState(String title) { - this.title = title; - } - - @Override - public String toString() { - return title; - } -} From a91eb38dd265df883e45fe62d71fa681597f39d9 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Thu, 26 Oct 2023 15:00:45 +0200 Subject: [PATCH 097/184] - rewrite ORF tutorial info code to use swing instead of JavaFX --- src/main/java/mediathek/Main.java | 4 -- .../java/mediathek/javafx/AustrianVlcCheck.kt | 62 ------------------- .../mediathek/mainwindow/AustrianVlcCheck.kt | 60 ++++++++++++++++++ .../mediathek/mainwindow/MediathekGui.java | 4 ++ 4 files changed, 64 insertions(+), 66 deletions(-) delete mode 100644 src/main/java/mediathek/javafx/AustrianVlcCheck.kt create mode 100644 src/main/java/mediathek/mainwindow/AustrianVlcCheck.kt diff --git a/src/main/java/mediathek/Main.java b/src/main/java/mediathek/Main.java index 5c788ca824..62fcbfd652 100644 --- a/src/main/java/mediathek/Main.java +++ b/src/main/java/mediathek/Main.java @@ -7,7 +7,6 @@ import mediathek.controller.history.SeenHistoryMigrator; import mediathek.daten.IndexedFilmList; import mediathek.gui.dialog.DialogStarteinstellungen; -import mediathek.javafx.AustrianVlcCheck; import mediathek.javafx.tool.JFXHiddenApplication; import mediathek.mac.MediathekGuiMac; import mediathek.mainwindow.MediathekGui; @@ -646,9 +645,6 @@ private static void startGuiMode() { window.toFront(); window.requestFocus(); } - //show a link to tutorial if we are in Austria and have never used MV before... - AustrianVlcCheck vlcCheck = new AustrianVlcCheck(); - vlcCheck.perform(); } private static MediathekGui getPlatformWindow() { diff --git a/src/main/java/mediathek/javafx/AustrianVlcCheck.kt b/src/main/java/mediathek/javafx/AustrianVlcCheck.kt deleted file mode 100644 index 35a08e311e..0000000000 --- a/src/main/java/mediathek/javafx/AustrianVlcCheck.kt +++ /dev/null @@ -1,62 +0,0 @@ -package mediathek.javafx - -import javafx.application.Platform -import javafx.event.EventHandler -import javafx.scene.control.Alert -import javafx.scene.control.Hyperlink -import javafx.scene.control.Label -import javafx.scene.layout.FlowPane -import mediathek.config.Konstanten -import mediathek.daten.Country -import mediathek.gui.actions.UrlHyperlinkAction -import mediathek.mainwindow.MediathekGui -import mediathek.tool.ApplicationConfiguration -import org.apache.logging.log4j.LogManager -import java.net.URISyntaxException - -class AustrianVlcCheck { - private lateinit var alert: Alert - private val config = ApplicationConfiguration.getConfiguration() - - private fun createLayout(): FlowPane { - val fp = FlowPane() - val lbl = Label( - """ - Um den ORF erfolgreich zu nutzen sind zusätzlich Einstellungen erforderlich. - Bitte lesen Sie sich hierzu folgenden Link durch: - """.trimIndent()) - val link = Hyperlink("Link zum Tutorial") - fp.children.addAll(lbl, link) - link.onAction = EventHandler { - //disable display of dialog when user has clicked on the hyperlink - config.setProperty(ApplicationConfiguration.APPLICATION_SHOW_ORF_CONFIG_HELP, false) - try { - UrlHyperlinkAction.openURL(MediathekGui.ui(), Konstanten.ORF_TUTORIAL_LINK) - } catch (ignored: URISyntaxException) { - } - alert.close() - } - return fp - } - - fun perform() { - logger.trace("ORF setup tutorial display check started") - if (config.getBoolean(ApplicationConfiguration.APPLICATION_SHOW_ORF_CONFIG_HELP, true)) { - //we haven´t shown the config help dialog before - if (ApplicationConfiguration.getInstance().geographicLocation == Country.AT) { - Platform.runLater { - val alert = Alert(Alert.AlertType.INFORMATION) - alert.title = Konstanten.PROGRAMMNAME - alert.headerText = "Wichtige Information für ORF" - alert.dialogPane.contentProperty().set(createLayout()) - alert.show() - } - } - } - logger.trace("ORF setup tutorial display check finished") - } - - companion object { - private val logger = LogManager.getLogger() - } -} \ No newline at end of file diff --git a/src/main/java/mediathek/mainwindow/AustrianVlcCheck.kt b/src/main/java/mediathek/mainwindow/AustrianVlcCheck.kt new file mode 100644 index 0000000000..b15ca0ab31 --- /dev/null +++ b/src/main/java/mediathek/mainwindow/AustrianVlcCheck.kt @@ -0,0 +1,60 @@ +package mediathek.mainwindow + +import mediathek.config.Konstanten +import mediathek.daten.Country +import mediathek.gui.actions.UrlHyperlinkAction +import mediathek.tool.ApplicationConfiguration +import mediathek.tool.TimerPool +import org.apache.logging.log4j.LogManager +import java.awt.Font +import java.util.concurrent.TimeUnit +import javax.swing.* +import javax.swing.event.HyperlinkEvent + +class AustrianVlcCheck(val owner: JFrame) { + private fun getFontWeight(font: Font): String { + return if (font.isBold) "bold" else "normal" + } + + private fun showSwingMessage() { + val font = UIManager.getFont("Label.font") + val boldFont = getFontWeight(font) + val style = "font-family:${font.family};font-weight:$boldFont;font-size: ${font.size}pt;" + val msg = + "Um den ORF erfolgreich zu nutzen sind zusätzliche Einstellungen erforderlich.
Bitte lesen Sie sich hierzu den Link durch." + + val ep = JEditorPane("text/html", msg) + ep.isEditable = false + ep.setBackground(UIManager.getColor("Label.background")) + ep.addHyperlinkListener { e: HyperlinkEvent -> + if (e.eventType == HyperlinkEvent.EventType.ACTIVATED) { + try { + ApplicationConfiguration.getConfiguration().setProperty(ApplicationConfiguration.APPLICATION_SHOW_ORF_CONFIG_HELP, false) + UrlHyperlinkAction.openURL(MediathekGui.ui(), Konstanten.ORF_TUTORIAL_LINK) + } catch (ex: Exception) { + logger.error("Failed to display ORF tutorial", ex) + } + } + } + + JOptionPane.showMessageDialog(owner, ep, "Wichtige Information für ORF", JOptionPane.WARNING_MESSAGE) + } + + fun perform() { + logger.trace("ORF setup tutorial display check started") + if (ApplicationConfiguration.getConfiguration().getBoolean(ApplicationConfiguration.APPLICATION_SHOW_ORF_CONFIG_HELP, true)) { + //we haven´t shown the config help dialog before + if (ApplicationConfiguration.getInstance().geographicLocation == Country.AT) { + logger.trace("Launching info dialog in 15 seconds...") + TimerPool.timerPool.schedule({ + SwingUtilities.invokeLater { showSwingMessage() } + }, 15, TimeUnit.SECONDS) + } + } + logger.trace("ORF setup tutorial display check finished") + } + + companion object { + private val logger = LogManager.getLogger() + } +} \ No newline at end of file diff --git a/src/main/java/mediathek/mainwindow/MediathekGui.java b/src/main/java/mediathek/mainwindow/MediathekGui.java index 63d9bb1e3f..5ce2b86921 100644 --- a/src/main/java/mediathek/mainwindow/MediathekGui.java +++ b/src/main/java/mediathek/mainwindow/MediathekGui.java @@ -258,6 +258,10 @@ public void onFailure(@NotNull Throwable t) { } }, Daten.getInstance().getDecoratedPool()); } + + //show a link to tutorial if we are in Austria and have never used MV before... + AustrianVlcCheck vlcCheck = new AustrianVlcCheck(this); + vlcCheck.perform(); } private void loadBandwidthMonitor() { From 9c18c632f120c0ee91895d9056cb89b23821ea44 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Thu, 26 Oct 2023 15:19:25 +0200 Subject: [PATCH 098/184] - refactor --- .../java/mediathek/mainwindow/MediathekGui.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/mediathek/mainwindow/MediathekGui.java b/src/main/java/mediathek/mainwindow/MediathekGui.java index 5ce2b86921..ced1370602 100644 --- a/src/main/java/mediathek/mainwindow/MediathekGui.java +++ b/src/main/java/mediathek/mainwindow/MediathekGui.java @@ -259,9 +259,16 @@ public void onFailure(@NotNull Throwable t) { }, Daten.getInstance().getDecoratedPool()); } - //show a link to tutorial if we are in Austria and have never used MV before... - AustrianVlcCheck vlcCheck = new AustrianVlcCheck(this); - vlcCheck.perform(); + performAustrianVlcCheck(); + } + + private void performAustrianVlcCheck() { + //perform check only when we are not in download-only mode... + if (!Config.shouldDownloadAndQuit()) { + //show a link to tutorial if we are in Austria and have never used MV before... + AustrianVlcCheck vlcCheck = new AustrianVlcCheck(this); + vlcCheck.perform(); + } } private void loadBandwidthMonitor() { From 565280776ca2f10bc23ba342bf93874a8b7c5b73 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Thu, 26 Oct 2023 15:43:13 +0200 Subject: [PATCH 099/184] - cleanup lucene index before statistics --- src/main/java/mediathek/mainwindow/MediathekGui.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/mediathek/mainwindow/MediathekGui.java b/src/main/java/mediathek/mainwindow/MediathekGui.java index ced1370602..994f9cb965 100644 --- a/src/main/java/mediathek/mainwindow/MediathekGui.java +++ b/src/main/java/mediathek/mainwindow/MediathekGui.java @@ -1118,14 +1118,14 @@ public boolean quitApplication(boolean shouldDownloadAndQuit) { logger.info("Write app config."); ApplicationConfiguration.getInstance().writeConfiguration(); + logger.info("Cleanup Lucene index."); + cleanupLuceneIndex(); + RuntimeStatistics.printRuntimeStatistics(); if (Config.isEnhancedLoggingEnabled()) { RuntimeStatistics.printDataUsageStatistics(); } - logger.info("Cleanup Lucene index."); - cleanupLuceneIndex(); - setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); if (isShutdownRequested()) { From 71d7d8f791311ca388e607e73994e83c5bb28f44 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Thu, 26 Oct 2023 16:56:25 +0200 Subject: [PATCH 100/184] -refactor --- .../mediathek/tool/RuntimeStatistics.java | 36 ------------------ .../java/mediathek/tool/RuntimeStatistics.kt | 37 +++++++++++++++++++ 2 files changed, 37 insertions(+), 36 deletions(-) delete mode 100644 src/main/java/mediathek/tool/RuntimeStatistics.java create mode 100644 src/main/java/mediathek/tool/RuntimeStatistics.kt diff --git a/src/main/java/mediathek/tool/RuntimeStatistics.java b/src/main/java/mediathek/tool/RuntimeStatistics.java deleted file mode 100644 index f22e04f569..0000000000 --- a/src/main/java/mediathek/tool/RuntimeStatistics.java +++ /dev/null @@ -1,36 +0,0 @@ -package mediathek.tool; - -import mediathek.tool.http.MVHttpClient; -import org.apache.logging.log4j.LogManager; - -import java.time.Duration; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.format.DateTimeFormatter; - -public class RuntimeStatistics { - - public static final LocalDateTime startZeit = LocalDateTime.now(); - - /** - * Output runtime statistics to console and log file - */ - public static void printRuntimeStatistics() { - DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; - final var endZeit = LocalDateTime.now(); - final var runTime = LocalTime.MIN.plusSeconds(Duration.between(startZeit, endZeit).toSeconds()); - - var logger = LogManager.getLogger(); - logger.info("################################################################################"); - logger.info(" --> Start: {}", formatter.format(startZeit)); - logger.info(" --> Ende: {}", formatter.format(endZeit)); - logger.info(" --> Laufzeit: {}h {}m {}s", runTime.getHour(),runTime.getMinute(),runTime.getSecond()); - } - - public static void printDataUsageStatistics() { - var byteCounter = MVHttpClient.getInstance().getByteCounter(); - var logger = LogManager.getLogger(); - logger.info("total data sent: {}", FileUtils.humanReadableByteCountBinary(byteCounter.totalBytesWritten())); - logger.info("total data received: {}", FileUtils.humanReadableByteCountBinary(byteCounter.totalBytesRead())); - } -} diff --git a/src/main/java/mediathek/tool/RuntimeStatistics.kt b/src/main/java/mediathek/tool/RuntimeStatistics.kt new file mode 100644 index 0000000000..18b479420d --- /dev/null +++ b/src/main/java/mediathek/tool/RuntimeStatistics.kt @@ -0,0 +1,37 @@ +package mediathek.tool + +import mediathek.tool.FileUtils.humanReadableByteCountBinary +import mediathek.tool.http.MVHttpClient +import org.apache.logging.log4j.LogManager +import org.apache.logging.log4j.Logger +import java.time.Duration +import java.time.LocalDateTime +import java.time.LocalTime +import java.time.format.DateTimeFormatter + +object RuntimeStatistics { + @JvmField + val startZeit: LocalDateTime = LocalDateTime.now() + val logger: Logger = LogManager.getLogger() + + /** + * Output runtime statistics to console and log file + */ + @JvmStatic + fun printRuntimeStatistics() { + val formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME + val endZeit = LocalDateTime.now() + val runTime = LocalTime.MIN.plusSeconds(Duration.between(startZeit, endZeit).toSeconds()) + + logger.info(" --> Start: ${formatter.format(startZeit)}") + logger.info(" --> Ende: ${formatter.format(endZeit)}") + logger.info(" --> Laufzeit: ${runTime.hour}h ${runTime.minute}m ${runTime.second}s") + } + + @JvmStatic + fun printDataUsageStatistics() { + val byteCounter = MVHttpClient.getInstance().byteCounter + logger.info("Total data sent: ${humanReadableByteCountBinary(byteCounter.totalBytesWritten())}") + logger.info("Total data received: ${humanReadableByteCountBinary(byteCounter.totalBytesRead())}") + } +} From cecc2f3743466671091d5b5cac826401d303ebe0 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Thu, 26 Oct 2023 17:26:08 +0200 Subject: [PATCH 101/184] - refactor --- .../{java => kotlin}/mediathek/gui/actions/CreateNewAboAction.kt | 0 .../{java => kotlin}/mediathek/gui/actions/ManageAboAction.kt | 0 .../mediathek/gui/actions/ResetFilterDialogPosition.kt | 0 .../{java => kotlin}/mediathek/gui/actions/ShowAboutAction.kt | 0 .../mediathek/gui/actions/ShowBandwidthUsageAction.kt | 0 .../{java => kotlin}/mediathek/gui/actions/ShowOnlineFaqAction.kt | 0 .../mediathek/gui/actions/ToggleDarkModeAction.kt | 0 .../mediathek/gui/actions/export/DiskSpaceUtil.kt | 0 .../gui/actions/export/ExportDecompressedFilmlistAction.kt | 0 .../mediathek/gui/actions/export/ExportReadableFilmlistAction.kt | 0 .../mediathek/gui/actions/export/FilmlistExportWorker.kt | 0 .../{java => kotlin}/mediathek/mainwindow/AustrianVlcCheck.kt | 0 src/main/{java => kotlin}/mediathek/mainwindow/FilmAgeLabel.kt | 0 .../mediathek/mainwindow/Log4jShutdownHookThread.kt | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename src/main/{java => kotlin}/mediathek/gui/actions/CreateNewAboAction.kt (100%) rename src/main/{java => kotlin}/mediathek/gui/actions/ManageAboAction.kt (100%) rename src/main/{java => kotlin}/mediathek/gui/actions/ResetFilterDialogPosition.kt (100%) rename src/main/{java => kotlin}/mediathek/gui/actions/ShowAboutAction.kt (100%) rename src/main/{java => kotlin}/mediathek/gui/actions/ShowBandwidthUsageAction.kt (100%) rename src/main/{java => kotlin}/mediathek/gui/actions/ShowOnlineFaqAction.kt (100%) rename src/main/{java => kotlin}/mediathek/gui/actions/ToggleDarkModeAction.kt (100%) rename src/main/{java => kotlin}/mediathek/gui/actions/export/DiskSpaceUtil.kt (100%) rename src/main/{java => kotlin}/mediathek/gui/actions/export/ExportDecompressedFilmlistAction.kt (100%) rename src/main/{java => kotlin}/mediathek/gui/actions/export/ExportReadableFilmlistAction.kt (100%) rename src/main/{java => kotlin}/mediathek/gui/actions/export/FilmlistExportWorker.kt (100%) rename src/main/{java => kotlin}/mediathek/mainwindow/AustrianVlcCheck.kt (100%) rename src/main/{java => kotlin}/mediathek/mainwindow/FilmAgeLabel.kt (100%) rename src/main/{java => kotlin}/mediathek/mainwindow/Log4jShutdownHookThread.kt (100%) diff --git a/src/main/java/mediathek/gui/actions/CreateNewAboAction.kt b/src/main/kotlin/mediathek/gui/actions/CreateNewAboAction.kt similarity index 100% rename from src/main/java/mediathek/gui/actions/CreateNewAboAction.kt rename to src/main/kotlin/mediathek/gui/actions/CreateNewAboAction.kt diff --git a/src/main/java/mediathek/gui/actions/ManageAboAction.kt b/src/main/kotlin/mediathek/gui/actions/ManageAboAction.kt similarity index 100% rename from src/main/java/mediathek/gui/actions/ManageAboAction.kt rename to src/main/kotlin/mediathek/gui/actions/ManageAboAction.kt diff --git a/src/main/java/mediathek/gui/actions/ResetFilterDialogPosition.kt b/src/main/kotlin/mediathek/gui/actions/ResetFilterDialogPosition.kt similarity index 100% rename from src/main/java/mediathek/gui/actions/ResetFilterDialogPosition.kt rename to src/main/kotlin/mediathek/gui/actions/ResetFilterDialogPosition.kt diff --git a/src/main/java/mediathek/gui/actions/ShowAboutAction.kt b/src/main/kotlin/mediathek/gui/actions/ShowAboutAction.kt similarity index 100% rename from src/main/java/mediathek/gui/actions/ShowAboutAction.kt rename to src/main/kotlin/mediathek/gui/actions/ShowAboutAction.kt diff --git a/src/main/java/mediathek/gui/actions/ShowBandwidthUsageAction.kt b/src/main/kotlin/mediathek/gui/actions/ShowBandwidthUsageAction.kt similarity index 100% rename from src/main/java/mediathek/gui/actions/ShowBandwidthUsageAction.kt rename to src/main/kotlin/mediathek/gui/actions/ShowBandwidthUsageAction.kt diff --git a/src/main/java/mediathek/gui/actions/ShowOnlineFaqAction.kt b/src/main/kotlin/mediathek/gui/actions/ShowOnlineFaqAction.kt similarity index 100% rename from src/main/java/mediathek/gui/actions/ShowOnlineFaqAction.kt rename to src/main/kotlin/mediathek/gui/actions/ShowOnlineFaqAction.kt diff --git a/src/main/java/mediathek/gui/actions/ToggleDarkModeAction.kt b/src/main/kotlin/mediathek/gui/actions/ToggleDarkModeAction.kt similarity index 100% rename from src/main/java/mediathek/gui/actions/ToggleDarkModeAction.kt rename to src/main/kotlin/mediathek/gui/actions/ToggleDarkModeAction.kt diff --git a/src/main/java/mediathek/gui/actions/export/DiskSpaceUtil.kt b/src/main/kotlin/mediathek/gui/actions/export/DiskSpaceUtil.kt similarity index 100% rename from src/main/java/mediathek/gui/actions/export/DiskSpaceUtil.kt rename to src/main/kotlin/mediathek/gui/actions/export/DiskSpaceUtil.kt diff --git a/src/main/java/mediathek/gui/actions/export/ExportDecompressedFilmlistAction.kt b/src/main/kotlin/mediathek/gui/actions/export/ExportDecompressedFilmlistAction.kt similarity index 100% rename from src/main/java/mediathek/gui/actions/export/ExportDecompressedFilmlistAction.kt rename to src/main/kotlin/mediathek/gui/actions/export/ExportDecompressedFilmlistAction.kt diff --git a/src/main/java/mediathek/gui/actions/export/ExportReadableFilmlistAction.kt b/src/main/kotlin/mediathek/gui/actions/export/ExportReadableFilmlistAction.kt similarity index 100% rename from src/main/java/mediathek/gui/actions/export/ExportReadableFilmlistAction.kt rename to src/main/kotlin/mediathek/gui/actions/export/ExportReadableFilmlistAction.kt diff --git a/src/main/java/mediathek/gui/actions/export/FilmlistExportWorker.kt b/src/main/kotlin/mediathek/gui/actions/export/FilmlistExportWorker.kt similarity index 100% rename from src/main/java/mediathek/gui/actions/export/FilmlistExportWorker.kt rename to src/main/kotlin/mediathek/gui/actions/export/FilmlistExportWorker.kt diff --git a/src/main/java/mediathek/mainwindow/AustrianVlcCheck.kt b/src/main/kotlin/mediathek/mainwindow/AustrianVlcCheck.kt similarity index 100% rename from src/main/java/mediathek/mainwindow/AustrianVlcCheck.kt rename to src/main/kotlin/mediathek/mainwindow/AustrianVlcCheck.kt diff --git a/src/main/java/mediathek/mainwindow/FilmAgeLabel.kt b/src/main/kotlin/mediathek/mainwindow/FilmAgeLabel.kt similarity index 100% rename from src/main/java/mediathek/mainwindow/FilmAgeLabel.kt rename to src/main/kotlin/mediathek/mainwindow/FilmAgeLabel.kt diff --git a/src/main/java/mediathek/mainwindow/Log4jShutdownHookThread.kt b/src/main/kotlin/mediathek/mainwindow/Log4jShutdownHookThread.kt similarity index 100% rename from src/main/java/mediathek/mainwindow/Log4jShutdownHookThread.kt rename to src/main/kotlin/mediathek/mainwindow/Log4jShutdownHookThread.kt From f8a923b9a8a1ce22651f411c04363e868c9d9007 Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Fri, 27 Oct 2023 07:41:17 +0200 Subject: [PATCH 102/184] - fix analyzer warnings --- .../java/mediathek/filmlisten/writer/FilmListWriter.java | 4 ++-- src/main/java/mediathek/mac/OsxPowerManager.java | 1 - src/main/java/mediathek/tool/FilenameUtils.java | 6 +++--- src/main/java/mediathek/tool/table/MVDownloadsTable.java | 8 ++++++-- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main/java/mediathek/filmlisten/writer/FilmListWriter.java b/src/main/java/mediathek/filmlisten/writer/FilmListWriter.java index c9a3c9fabd..21f586fde1 100644 --- a/src/main/java/mediathek/filmlisten/writer/FilmListWriter.java +++ b/src/main/java/mediathek/filmlisten/writer/FilmListWriter.java @@ -52,8 +52,8 @@ private void checkOsxCacheDirectory() { if (Files.notExists(filePath)) { try { Files.createDirectories(filePath); - } catch (IOException ioException) { - ioException.printStackTrace(); + } catch (IOException e) { + logger.error("checkOsxCacheDirectory", e); } } } diff --git a/src/main/java/mediathek/mac/OsxPowerManager.java b/src/main/java/mediathek/mac/OsxPowerManager.java index 74870b0b2b..c3da363846 100644 --- a/src/main/java/mediathek/mac/OsxPowerManager.java +++ b/src/main/java/mediathek/mac/OsxPowerManager.java @@ -25,7 +25,6 @@ public void disablePowerManagement() { catch (IOException e) { caffeinateProcess = null; logger.error("disabling power management failed", e); - e.printStackTrace(); } } diff --git a/src/main/java/mediathek/tool/FilenameUtils.java b/src/main/java/mediathek/tool/FilenameUtils.java index 38dcbf48f9..14796a85f2 100644 --- a/src/main/java/mediathek/tool/FilenameUtils.java +++ b/src/main/java/mediathek/tool/FilenameUtils.java @@ -19,7 +19,7 @@ public class FilenameUtils { /** * Valid characters for Windows in file names: - * Based on http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx + * Based on MSDN sample */ public static final String REGEXP_ILLEGAL_CHARACTERS_WINDOWS = "[:\\\\/*?|<>\"]"; public static final String REGEXP_ILLEGAL_CHARACTERS_WINDOWS_PATH = "[:/*?|<>\"]"; @@ -128,7 +128,7 @@ private static String convertToNativeEncoding(String fileName, boolean isPath) { //remove NUL character from conversion... ret = ret.replaceAll("\\u0000", ""); } catch (CharacterCodingException e) { - e.printStackTrace(); + logger.error("convertToNativeEncoding", e); } return ret; @@ -171,7 +171,7 @@ private static String convertToASCIIEncoding(String fileName, boolean isPath) { //remove NUL character from conversion... ret = ret.replaceAll("\\u0000", ""); } catch (CharacterCodingException e) { - e.printStackTrace(); + logger.error("convertToASCIIEncoding", e); } return ret; diff --git a/src/main/java/mediathek/tool/table/MVDownloadsTable.java b/src/main/java/mediathek/tool/table/MVDownloadsTable.java index 58988c0004..a1c77a14e0 100644 --- a/src/main/java/mediathek/tool/table/MVDownloadsTable.java +++ b/src/main/java/mediathek/tool/table/MVDownloadsTable.java @@ -7,6 +7,8 @@ import mediathek.tool.MessageBus; import mediathek.tool.models.TModel; import mediathek.tool.models.TModelDownload; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import javax.activation.DataHandler; import javax.swing.*; @@ -155,11 +157,13 @@ public boolean canImport(TransferHandler.TransferSupport info) { // here's the problem // canImport is called during drags AND before drop is accepted } catch (Exception e) { - e.printStackTrace(); + logger.error("canImport", e); } return true; } + private static final Logger logger = LogManager.getLogger(); + @Override public int getSourceActions(JComponent c) { return TransferHandler.COPY_OR_MOVE; @@ -183,7 +187,7 @@ public boolean importData(TransferHandler.TransferSupport info) { return true; } } catch (Exception ex) { - ex.printStackTrace(); + logger.error("importData", ex); } return false; } From 4d15bef3f3b91f6a17c4d7b1cb5f5fe57e03396a Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Fri, 27 Oct 2023 07:59:50 +0200 Subject: [PATCH 103/184] - add missing tags --- src/main/java/mediathek/daten/abo/AboTags.kt | 4 ++-- .../daten/blacklist/BlacklistTags.kt | 2 +- .../mediathek/tool/dns/IPvPreferenceMode.kt | 2 +- .../kotlin/mediathek/daten/abo/AboTagsTest.kt | 22 +++++++++++++++++++ .../daten/blacklist/BlacklistTagsTest.kt | 15 +++++++++++++ .../tool/dns/IPvPreferenceModeTest.kt | 13 +++++++++++ 6 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 src/test/kotlin/mediathek/daten/abo/AboTagsTest.kt create mode 100644 src/test/kotlin/mediathek/daten/blacklist/BlacklistTagsTest.kt create mode 100644 src/test/kotlin/mediathek/tool/dns/IPvPreferenceModeTest.kt diff --git a/src/main/java/mediathek/daten/abo/AboTags.kt b/src/main/java/mediathek/daten/abo/AboTags.kt index afc32ae642..34b6354f61 100644 --- a/src/main/java/mediathek/daten/abo/AboTags.kt +++ b/src/main/java/mediathek/daten/abo/AboTags.kt @@ -20,12 +20,12 @@ enum class AboTags(val index: Int, val xmlName: String) { companion object { @JvmStatic fun fromXmlTag(tag: String): Optional { - return Arrays.stream(values()).filter { e: AboTags -> e.xmlName == tag }.findAny() + return Arrays.stream(entries.toTypedArray()).filter { e: AboTags -> e.xmlName == tag }.findAny() } @JvmStatic fun fromIndex(index: Int): Optional { - return Arrays.stream(values()).filter { e: AboTags -> e.index == index }.findAny() + return Arrays.stream(entries.toTypedArray()).filter { e: AboTags -> e.index == index }.findAny() } } } \ No newline at end of file diff --git a/src/main/java/mediathek/daten/blacklist/BlacklistTags.kt b/src/main/java/mediathek/daten/blacklist/BlacklistTags.kt index f4a821e13c..42d570d87b 100644 --- a/src/main/java/mediathek/daten/blacklist/BlacklistTags.kt +++ b/src/main/java/mediathek/daten/blacklist/BlacklistTags.kt @@ -11,7 +11,7 @@ enum class BlacklistTags(val index: Int, val xmlName: String) { companion object { @JvmStatic fun fromXmlTag(tag: String): Optional { - return Arrays.stream(values()).filter { e: BlacklistTags -> e.xmlName == tag }.findAny() + return Arrays.stream(entries.toTypedArray()).filter { e: BlacklistTags -> e.xmlName == tag }.findAny() } } } \ No newline at end of file diff --git a/src/main/kotlin/mediathek/tool/dns/IPvPreferenceMode.kt b/src/main/kotlin/mediathek/tool/dns/IPvPreferenceMode.kt index eb136f5518..a34f74657a 100644 --- a/src/main/kotlin/mediathek/tool/dns/IPvPreferenceMode.kt +++ b/src/main/kotlin/mediathek/tool/dns/IPvPreferenceMode.kt @@ -17,6 +17,6 @@ enum class IPvPreferenceMode(val code: String) { companion object { @JvmStatic fun fromString(ipMode: String): IPvPreferenceMode = - values().find { it.code == ipMode } ?: throw IllegalArgumentException("Unknown value $ipMode") + entries.find { it.code == ipMode } ?: throw IllegalArgumentException("Unknown value $ipMode") } } \ No newline at end of file diff --git a/src/test/kotlin/mediathek/daten/abo/AboTagsTest.kt b/src/test/kotlin/mediathek/daten/abo/AboTagsTest.kt new file mode 100644 index 0000000000..ffa5704a2b --- /dev/null +++ b/src/test/kotlin/mediathek/daten/abo/AboTagsTest.kt @@ -0,0 +1,22 @@ +package mediathek.daten.abo + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Test + +class AboTagsTest { + + @Test + fun fromXmlTag() { + val r = AboTags.fromXmlTag("Sender") + assertTrue(r.isPresent) + assertEquals(r.get(), AboTags.SENDER) + } + + @Test + fun fromIndex() { + val r = AboTags.fromIndex(DatenAbo.ABO_NR) + assertTrue(r.isPresent) + assertEquals(r.get(), AboTags.NR) + } +} \ No newline at end of file diff --git a/src/test/kotlin/mediathek/daten/blacklist/BlacklistTagsTest.kt b/src/test/kotlin/mediathek/daten/blacklist/BlacklistTagsTest.kt new file mode 100644 index 0000000000..d9482a4e53 --- /dev/null +++ b/src/test/kotlin/mediathek/daten/blacklist/BlacklistTagsTest.kt @@ -0,0 +1,15 @@ +package mediathek.daten.blacklist + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Test + +class BlacklistTagsTest { + + @Test + fun fromXmlTag() { + val r = BlacklistTags.fromXmlTag("black-sender") + assertTrue(r.isPresent) + assertEquals(r.get(), BlacklistTags.SENDER) + } +} \ No newline at end of file diff --git a/src/test/kotlin/mediathek/tool/dns/IPvPreferenceModeTest.kt b/src/test/kotlin/mediathek/tool/dns/IPvPreferenceModeTest.kt new file mode 100644 index 0000000000..eb745b5ded --- /dev/null +++ b/src/test/kotlin/mediathek/tool/dns/IPvPreferenceModeTest.kt @@ -0,0 +1,13 @@ +package mediathek.tool.dns + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +class IPvPreferenceModeTest { + + @Test + fun fromString() { + val r = IPvPreferenceMode.fromString("ip_v6_only") + assertEquals(IPvPreferenceMode.IPV6_ONLY, r) + } +} \ No newline at end of file From 9bc3e6a816b40d92400cac54a64c49bc21685d2b Mon Sep 17 00:00:00 2001 From: "Christian F." Date: Fri, 27 Oct 2023 08:15:35 +0200 Subject: [PATCH 104/184] - fix warnings --- .../res/programm/fxml/bookmarkNoteDialog.fxml | 88 +++++++++++-------- 1 file changed, 49 insertions(+), 39 deletions(-) diff --git a/src/main/resources/mediathek/res/programm/fxml/bookmarkNoteDialog.fxml b/src/main/resources/mediathek/res/programm/fxml/bookmarkNoteDialog.fxml index 8c2e3c0e0e..27d903add5 100644 --- a/src/main/resources/mediathek/res/programm/fxml/bookmarkNoteDialog.fxml +++ b/src/main/resources/mediathek/res/programm/fxml/bookmarkNoteDialog.fxml @@ -1,47 +1,57 @@ - - - - - - - + + - - - - -