diff --git a/src/main/java/mediathek/javafx/bookmark/BookmarkNoteDialog.java b/src/main/java/mediathek/javafx/bookmark/BookmarkNoteDialog.java deleted file mode 100644 index c48eb01e44..0000000000 --- a/src/main/java/mediathek/javafx/bookmark/BookmarkNoteDialog.java +++ /dev/null @@ -1,249 +0,0 @@ -package mediathek.javafx.bookmark; - -import javafx.concurrent.Task; -import javafx.concurrent.WorkerStateEvent; -import javafx.event.Event; -import javafx.fxml.FXML; -import javafx.fxml.Initializable; -import javafx.scene.control.*; -import javafx.stage.Stage; -import mediathek.tool.http.MVHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import okhttp3.ResponseBody; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; -import java.util.ResourceBundle; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - - -/** - * Dialog to set expiry date and notes for bookmarked movies - * - * includes search for movies's expiry date on webpage - * - * @author Klaus Wich - */ - -public class BookmarkNoteDialog implements Initializable -{ - @FXML - private DatePicker fxDate; - @FXML - private TextArea fxNote; - @FXML - protected Button SaveButton; - @FXML - protected Button CancelButton; - @FXML - protected Button btnWebDate; - @FXML - private ProgressIndicator fxProgress; - @FXML - private Label fxStatus; - @FXML - private Label fxResult; - @FXML - private Label fxExpiry; - - protected Stage dlgstage; - protected boolean datachanged; - private BookmarkData data; - private DateTimeFormatter dateformatter; - private boolean hasWebURL; - - @Override - public void initialize(URL arg0, ResourceBundle arg1) { - dateformatter = DateTimeFormatter.ofPattern("dd.MM.yyyy"); - fxDate.setOnKeyTyped((var e) -> handleChange()); - fxDate.setOnMouseClicked((var e) -> handleChange()); - fxDate.getEditor().setOnKeyTyped((var e) -> handleChange()); - } - - @FXML - protected void handleCancel() { - datachanged = false; - dlgstage.hide(); - } - - @FXML - protected void handleSave() { - if (!fxNote.getText().equals(data.getNote())) { - data.setNote(fxNote.getText()); - datachanged = true; - } - - String dv = getDateValue(); - if (!(dv == null && data.getExpiry() == null) || (dv != null && !dv.equals(data.getExpiry()))) { - data.setExpiry(dv); - datachanged = true; - } - dlgstage.hide(); - } - - @FXML - protected void handleChange() { - boolean isok = Verify(); - SaveButton.setDisable(!isok); - int idx = fxDate.getEditor().getStyleClass().indexOf("Invalid"); - if (isok && idx > -1) { - fxDate.getEditor().getStyleClass().remove("Invalid"); - } - else if (!isok && idx == -1) { - fxDate.getEditor().getStyleClass().add("Invalid"); - } - } - - /** - * Search the expiry date on Webpage - * @param e - * - * Starts own background task - */ - @FXML - private void btnSearchWeb(Event e) { - fxProgress.setVisible(true); - fxStatus.setVisible(true); - btnWebDate.setDisable(true); - Task task = new Task<>() { - @Override - protected String call() { - return searchExpiryDate(); - } - }; - task.setOnSucceeded((WorkerStateEvent t) -> { - String result = task.getValue(); - if (result != null) { - fxResult.setText("\"Verfügbar bis Datum\" -" + result + "- gefunden"); - fxDate.getEditor().setText(result); - } - else { - fxResult.setText("\"Verfügbar bis\" Datum nicht gefunden"); - } - fxProgress.setVisible(false); - fxStatus.setVisible(false); - btnWebDate.setDisable(false); - }); - new Thread(task).start(); - } - - public final boolean SetandShow(Stage dlgstage, BookmarkData data) { - this.dlgstage = dlgstage; - this.data = data; - this.hasWebURL = data.hasWebURL(); - this.dlgstage.setTitle(data.getNote() != null || data.getExpiry() != null ? "Anmerkungen ändern" : "neue Anmerkungen"); - fxNote.setText(data.getNote() != null ? data.getNote() : ""); - if (data.isLiveStream()) { // For live stream disable expiry handling - fxExpiry.setDisable(true); - fxDate.setDisable(true); - btnWebDate.setDisable(true); - } - else { - if (data.getExpiry() != null && !data.getExpiry().isEmpty()) { // copy expiry from record - try { - fxDate.setValue(LocalDate.parse(data.getExpiry(),dateformatter)); - } - catch (Exception ignored) {} - } - btnWebDate.setDisable(!hasWebURL); - } - handleChange(); - // Display the Dialog and wait - this.dlgstage.showAndWait(); - return datachanged; - } - - protected boolean Verify() { - boolean rc = true; - // Check date format: - String dv = getDateValue(); - if (dv != null) { - try { - LocalDate.parse(dv, dateformatter); - } - catch (Exception e) { - rc = false; - } - } - return rc; - } - - /** - * Get date value or null - * @return String - */ - private String getDateValue() { - String dv = fxDate.getEditor().getText(); - if (dv != null && dv.isEmpty()) { - dv = null; - } - return dv; - } - - /** - * Try to retrieve the expiry date from the associated webpage - */ - private static final Pattern[] DATE_PATTERNS = {null, null}; - private static final String[] DATE_PATTERN_STRINGS = {"verfügbar.+?bis.+?([0-9]{2}\\.[0-9]{2}\\.[0-9]{4})", "verfügbar.+?bis.+?([0-9]{2}/[0-9]{2}/[0-9]{4})"}; - private static final int EXCERPT_LEN = 1000; - - private String searchExpiryDate() { - String result = null; - if (hasWebURL) { - final Request request = new Request.Builder().url(data.getWebUrl()).get().build(); - try (Response response = MVHttpClient.getInstance().getHttpClient().newCall(request).execute(); - ResponseBody body = response.body()) { - if (response.isSuccessful() && body != null) { - try (var is = body.byteStream(); - var isr = new InputStreamReader(is, StandardCharsets.UTF_8); - BufferedReader in = new BufferedReader(isr)) { - StringBuilder a = new StringBuilder(); - String str; - boolean save = false; - // 1.) get EXCERPT_LEN characters beginning with the search term - while ((str = in.readLine()) != null) { - if (!save) { - int idx = str.toLowerCase().indexOf("verfügbar "); - if (idx > -1) { - String sdate = str.substring(idx, str.length() - 1); // < idx+EXCERPT_LEN ? str.length() : idx+EXCERPT_LEN); - a.append(sdate); - save = true; - } - } else { - if (a.length() < EXCERPT_LEN) { - a.append(str.toLowerCase()); - } else { - break; - } - } - } - - if (!a.isEmpty()) { - // 2.) use regex to extract date - for (int k = 0; k < DATE_PATTERNS.length; k++) { - if (DATE_PATTERNS[k] == null) { // compile pattern only once! - DATE_PATTERNS[k] = Pattern.compile(DATE_PATTERN_STRINGS[k], Pattern.CASE_INSENSITIVE); - } - Matcher matcher = DATE_PATTERNS[k].matcher(a); - if (matcher.find()) { - result = matcher.group(1).replaceAll("/", "\\."); - break; - } - } - } - } - } - } catch (IOException ignored) { - } - } - - return result; - } -} diff --git a/src/main/java/mediathek/javafx/bookmark/BookmarkNoteDialogController.java b/src/main/java/mediathek/javafx/bookmark/BookmarkNoteDialogController.java new file mode 100644 index 0000000000..289eb8e393 --- /dev/null +++ b/src/main/java/mediathek/javafx/bookmark/BookmarkNoteDialogController.java @@ -0,0 +1,187 @@ +package mediathek.javafx.bookmark; + +import javafx.concurrent.WorkerStateEvent; +import javafx.event.Event; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.*; +import javafx.stage.Stage; +import mediathek.config.Konstanten; + +import java.net.URL; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.ResourceBundle; + + +/** + * Dialog to set expiry date and notes for bookmarked movies + *

+ * includes search for movies's expiry date on webpage + * + * @author Klaus Wich + */ + +public class BookmarkNoteDialogController implements Initializable { + /** + * Try to retrieve the expiry date from the associated webpage + */ + private final DateTimeFormatter dateformatter; + @FXML + protected Button SaveButton; + @FXML + protected Button CancelButton; + @FXML + protected Button btnWebDate; + protected Stage dlgstage; + protected boolean datachanged; + @FXML + private DatePicker fxDate; + @FXML + private TextArea fxNote; + @FXML + private ProgressIndicator fxProgress; + @FXML + private Label fxStatus; + @FXML + private Label fxExpiry; + private BookmarkData data; + private boolean hasWebURL; + + public BookmarkNoteDialogController() { + dateformatter = DateTimeFormatter.ofPattern("dd.MM.yyyy"); + } + + @Override + public void initialize(URL arg0, ResourceBundle arg1) { + fxDate.setOnKeyTyped((var e) -> handleChange()); + fxDate.setOnMouseClicked((var e) -> handleChange()); + fxDate.getEditor().setOnKeyTyped((var e) -> handleChange()); + + ButtonBar.setButtonData(CancelButton, ButtonBar.ButtonData.CANCEL_CLOSE); + ButtonBar.setButtonData(SaveButton, ButtonBar.ButtonData.OK_DONE); + } + + @FXML + protected void handleCancel() { + datachanged = false; + dlgstage.hide(); + } + + @FXML + protected void handleSave() { + if (!fxNote.getText().equals(data.getNote())) { + data.setNote(fxNote.getText()); + datachanged = true; + } + + String dv = getDateValue(); + if (!(dv == null && data.getExpiry() == null) || (dv != null && !dv.equals(data.getExpiry()))) { + data.setExpiry(dv); + datachanged = true; + } + dlgstage.hide(); + } + + @FXML + protected void handleChange() { + boolean isok = Verify(); + SaveButton.setDisable(!isok); + int idx = fxDate.getEditor().getStyleClass().indexOf("Invalid"); + if (isok && idx > -1) { + fxDate.getEditor().getStyleClass().remove("Invalid"); + } else if (!isok && idx == -1) { + fxDate.getEditor().getStyleClass().add("Invalid"); + } + } + + /** + * Search the expiry date on Webpage + * + * @param e Starts own background task + */ + @FXML + private void btnSearchWeb(Event e) { + fxProgress.setVisible(true); + fxStatus.setVisible(true); + btnWebDate.setDisable(true); + var searchExpirationDateTask = new SearchExpirationDateTask(hasWebURL, data.getWebUrl()); + searchExpirationDateTask.setOnSucceeded((WorkerStateEvent t) -> { + fxProgress.setVisible(false); + fxStatus.setVisible(false); + + String result = searchExpirationDateTask.getValue(); + Alert alert = new Alert(Alert.AlertType.NONE); + alert.initOwner(dlgstage); + alert.setTitle(Konstanten.PROGRAMMNAME); + alert.setHeaderText("Suche nach Datum"); + + if (result != null) { + alert.setAlertType(Alert.AlertType.INFORMATION); + var msg = String.format("Verfügbarkeit bis %s wurde gefunden.", result); + alert.setContentText(msg); + fxDate.getEditor().setText(result); + } else { + alert.setAlertType(Alert.AlertType.WARNING); + alert.setContentText("Es konnte keine Verfügbarkeit gefunden werden."); + } + alert.showAndWait(); + + btnWebDate.setDisable(false); + }); + new Thread(searchExpirationDateTask).start(); + } + + public final boolean SetandShow(Stage dlgstage, BookmarkData data) { + this.dlgstage = dlgstage; + this.data = data; + this.hasWebURL = data.hasWebURL(); + this.dlgstage.setTitle(data.getNote() != null || data.getExpiry() != null ? "Anmerkungen ändern" : "Neue Anmerkungen"); + fxNote.setText(data.getNote() != null ? data.getNote() : ""); + if (data.isLiveStream()) { // For live stream disable expiry handling + fxExpiry.setDisable(true); + fxDate.setDisable(true); + btnWebDate.setDisable(true); + } else { + if (data.getExpiry() != null && !data.getExpiry().isEmpty()) { // copy expiry from record + try { + fxDate.setValue(LocalDate.parse(data.getExpiry(), dateformatter)); + } catch (Exception ignored) { + } + } + btnWebDate.setDisable(!hasWebURL); + } + handleChange(); + // Display the Dialog and wait + this.dlgstage.showAndWait(); + return datachanged; + } + + protected boolean Verify() { + boolean rc = true; + // Check date format: + String dv = getDateValue(); + if (dv != null) { + try { + LocalDate.parse(dv, dateformatter); + } catch (Exception e) { + rc = false; + } + } + return rc; + } + + /** + * Get date value or null + * + * @return String + */ + private String getDateValue() { + String dv = fxDate.getEditor().getText(); + if (dv != null && dv.isEmpty()) { + dv = null; + } + return dv; + } + +} diff --git a/src/main/java/mediathek/javafx/bookmark/BookmarkWindowController.java b/src/main/java/mediathek/javafx/bookmark/BookmarkWindowController.java index f30c9355f1..f1866dfd4e 100644 --- a/src/main/java/mediathek/javafx/bookmark/BookmarkWindowController.java +++ b/src/main/java/mediathek/javafx/bookmark/BookmarkWindowController.java @@ -135,8 +135,6 @@ public class BookmarkWindowController implements Initializable { @FXML private Label lblSeen; @FXML - private Label lblMessage; - @FXML private Label lblFilter; @FXML private TextArea taDescription; @@ -220,10 +218,9 @@ private void btnEditNote(Event e) { dlgstage.initOwner(this.stage); try { FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/mediathek/res/programm/fxml/bookmarkNoteDialog.fxml")); - BookmarkNoteDialog bdialog = new BookmarkNoteDialog(); + BookmarkNoteDialogController bdialog = new BookmarkNoteDialogController(); fxmlLoader.setController(bdialog); Scene scene = new Scene(fxmlLoader.load()); - scene.getStylesheets().add(getClass().getResource("/mediathek/res/css/bookmarkNoteDialog.css").toExternalForm()); dlgstage.getIcons().add(new Image("/mediathek/res/MediathekView.png")); dlgstage.setScene(scene); if (bdialog.SetandShow(dlgstage, tbBookmarks.getSelectionModel().getSelectedItem())) { @@ -626,7 +623,6 @@ private void updateDisplay() { 30, TimeUnit.SECONDS); } - lblMessage.setText(""); } /** @@ -636,7 +632,6 @@ private void saveBookMarkList() { if (listUpdated) { listeBookmarkList.saveToFile(StandardLocations.getBookmarkFilePath()); btnSaveList.setDisable(true); - JavaFxUtils.invokeInFxThreadAndWait(() -> lblMessage.setText("Merkliste ist gesichert")); } listUpdated = false; } diff --git a/src/main/java/mediathek/javafx/bookmark/SearchExpirationDateTask.java b/src/main/java/mediathek/javafx/bookmark/SearchExpirationDateTask.java new file mode 100644 index 0000000000..5a57bdbb3e --- /dev/null +++ b/src/main/java/mediathek/javafx/bookmark/SearchExpirationDateTask.java @@ -0,0 +1,85 @@ +package mediathek.javafx.bookmark; + +import javafx.concurrent.Task; +import mediathek.tool.http.MVHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +class SearchExpirationDateTask extends Task { + private static final int EXCERPT_LEN = 1000; + private static final Pattern[] DATE_PATTERNS = {null, null}; + private static final String[] DATE_PATTERN_STRINGS = {"verfügbar.+?bis.+?([0-9]{2}\\.[0-9]{2}\\.[0-9]{4})", "verfügbar.+?bis.+?([0-9]{2}/[0-9]{2}/[0-9]{4})"}; + private final boolean hasWebURL; + private final String url; + + public SearchExpirationDateTask(boolean hasWebURL, String url) { + this.hasWebURL = hasWebURL; + this.url = url; + } + + @Override + protected String call() throws Exception { + return searchExpiryDate(); + } + + private String searchExpiryDate() { + String result = null; + if (hasWebURL) { + final Request request = new Request.Builder().url(url).get().build(); + try (Response response = MVHttpClient.getInstance().getHttpClient().newCall(request).execute(); + ResponseBody body = response.body()) { + if (response.isSuccessful() && body != null) { + try (var is = body.byteStream(); + var isr = new InputStreamReader(is, StandardCharsets.UTF_8); + BufferedReader in = new BufferedReader(isr)) { + StringBuilder a = new StringBuilder(); + String str; + boolean save = false; + // 1.) get EXCERPT_LEN characters beginning with the search term + while ((str = in.readLine()) != null) { + if (!save) { + int idx = str.toLowerCase().indexOf("verfügbar "); + if (idx > -1) { + String sdate = str.substring(idx, str.length() - 1); // < idx+EXCERPT_LEN ? str.length() : idx+EXCERPT_LEN); + a.append(sdate); + save = true; + } + } else { + if (a.length() < EXCERPT_LEN) { + a.append(str.toLowerCase()); + } else { + break; + } + } + } + + if (!a.isEmpty()) { + // 2.) use regex to extract date + for (int k = 0; k < DATE_PATTERNS.length; k++) { + if (DATE_PATTERNS[k] == null) { // compile pattern only once! + DATE_PATTERNS[k] = Pattern.compile(DATE_PATTERN_STRINGS[k], Pattern.CASE_INSENSITIVE); + } + Matcher matcher = DATE_PATTERNS[k].matcher(a); + if (matcher.find()) { + result = matcher.group(1).replaceAll("/", "\\."); + break; + } + } + } + } + } + } catch (IOException ignored) { + } + } + + return result; + } +} diff --git a/src/main/resources/mediathek/res/css/bookmarkNoteDialog.css b/src/main/resources/mediathek/res/css/bookmarkNoteDialog.css deleted file mode 100644 index 5fcbe3c334..0000000000 --- a/src/main/resources/mediathek/res/css/bookmarkNoteDialog.css +++ /dev/null @@ -1,9 +0,0 @@ - -.root { - -fx-font-size: 11px -} - -.Invalid { - -fx-text-fill: red; - -fx-font-weight: bold; -} diff --git a/src/main/resources/mediathek/res/css/description.css b/src/main/resources/mediathek/res/css/description.css deleted file mode 100644 index df1570edf4..0000000000 --- a/src/main/resources/mediathek/res/css/description.css +++ /dev/null @@ -1,15 +0,0 @@ -span { - font-family: -apple-system, BlinkMacSystemFont, - "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", - "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; -} - -.headline { - font-weight: bold; - font-size: 1em; -} - -.description { - font-size: 0.8em; -} diff --git a/src/main/resources/mediathek/res/css/splashscreen.css b/src/main/resources/mediathek/res/css/splashscreen.css deleted file mode 100644 index 1a759f47e5..0000000000 --- a/src/main/resources/mediathek/res/css/splashscreen.css +++ /dev/null @@ -1,31 +0,0 @@ -#progressText { - -fx-font-size: 0.833333em; - -fx-text-fill: white; -} - -#progressBar .bar { - -fx-padding: 2px; - -fx-background-insets: 0; - -fx-text-box-border: black; -} - -#appName { - -fx-text-fill: white; - -fx-font-weight: bold; - -fx-font-size: 5em; -} - -#appVersion { - -fx-text-fill: white; - -fx-font-weight: bold; - -fx-font-size: 1.25em; -} - -#vbox { - -fx-background-color: linear-gradient(to bottom, #323333, #17171a); - -fx-padding: 10; -} - -#image { - -fx-alignment: right; -} \ No newline at end of file diff --git a/src/main/resources/mediathek/res/css/toolpanel.css b/src/main/resources/mediathek/res/css/toolpanel.css deleted file mode 100644 index be9f6c416c..0000000000 --- a/src/main/resources/mediathek/res/css/toolpanel.css +++ /dev/null @@ -1,17 +0,0 @@ - -.togglebutton { - -fx-background-color: #006900; -} - -.togglebutton.selected { - -fx-background-color: #4169e1; - -fx-border-color: #ff0000; -} - -.togglebutton.hover { - -fx-background-color: #87cefa; -} - -.button:hover { - -fx-background-color: #87cefa; -} \ No newline at end of file diff --git a/src/main/resources/mediathek/res/programm/fxml/bookmarkNoteDialog.fxml b/src/main/resources/mediathek/res/programm/fxml/bookmarkNoteDialog.fxml index e5989461bb..9d5b5576b7 100644 --- a/src/main/resources/mediathek/res/programm/fxml/bookmarkNoteDialog.fxml +++ b/src/main/resources/mediathek/res/programm/fxml/bookmarkNoteDialog.fxml @@ -4,45 +4,33 @@ - - -