Improve recording relation action behaviour
This commit is contained in:
parent
b8467fc673
commit
9b9659be71
|
@ -0,0 +1,80 @@
|
||||||
|
package ctbrec.ui;
|
||||||
|
|
||||||
|
import static ctbrec.SubsequentAction.*;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import ctbrec.Model;
|
||||||
|
import ctbrec.SubsequentAction;
|
||||||
|
import ctbrec.ui.controls.DateTimePicker;
|
||||||
|
import ctbrec.ui.controls.Dialogs;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.scene.Cursor;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.RadioButton;
|
||||||
|
import javafx.scene.control.ToggleGroup;
|
||||||
|
import javafx.scene.layout.GridPane;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
|
||||||
|
public class RecordUntilDialog {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(RecordUntilDialog.class);
|
||||||
|
|
||||||
|
private Node source;
|
||||||
|
private Model model;
|
||||||
|
|
||||||
|
private RadioButton pauseButton;
|
||||||
|
private DateTimePicker datePicker;
|
||||||
|
private GridPane gridPane = new GridPane();
|
||||||
|
|
||||||
|
public RecordUntilDialog(Node source, Model model) {
|
||||||
|
this.source = source;
|
||||||
|
this.model = model;
|
||||||
|
createGui();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createGui() {
|
||||||
|
source.setCursor(Cursor.WAIT);
|
||||||
|
datePicker = new DateTimePicker();
|
||||||
|
gridPane.setHgap(10);
|
||||||
|
gridPane.setVgap(10);
|
||||||
|
gridPane.setPadding(new Insets(20, 150, 10, 10));
|
||||||
|
gridPane.add(new Label("Stop at"), 0, 0);
|
||||||
|
gridPane.add(datePicker, 1, 0);
|
||||||
|
gridPane.add(new Label("And then"), 0, 1);
|
||||||
|
var toggleGroup = new ToggleGroup();
|
||||||
|
pauseButton = new RadioButton("pause recording");
|
||||||
|
pauseButton.setSelected(model.getRecordUntilSubsequentAction() == PAUSE);
|
||||||
|
pauseButton.setToggleGroup(toggleGroup);
|
||||||
|
var removeButton = new RadioButton("remove model");
|
||||||
|
removeButton.setSelected(model.getRecordUntilSubsequentAction() == REMOVE);
|
||||||
|
removeButton.setToggleGroup(toggleGroup);
|
||||||
|
var row = new HBox();
|
||||||
|
row.getChildren().addAll(pauseButton, removeButton);
|
||||||
|
HBox.setMargin(pauseButton, new Insets(5));
|
||||||
|
HBox.setMargin(removeButton, new Insets(5));
|
||||||
|
gridPane.add(row, 1, 1);
|
||||||
|
if (model.isRecordingTimeLimited()) {
|
||||||
|
var localDate = LocalDateTime.ofInstant(model.getRecordUntil(), ZoneId.systemDefault());
|
||||||
|
datePicker.setDateTimeValue(localDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean showAndWait() {
|
||||||
|
boolean confirmed = Dialogs.showCustomInput(source.getScene(), "Stop Recording of " + model.getDisplayName() + " at", gridPane);
|
||||||
|
if (confirmed) {
|
||||||
|
SubsequentAction action = pauseButton.isSelected() ? PAUSE : REMOVE;
|
||||||
|
LOG.info("Stop at {} and {}", datePicker.getDateTimeValue(), action);
|
||||||
|
var stopAt = Instant.from(datePicker.getDateTimeValue().atZone(ZoneId.systemDefault()));
|
||||||
|
model.setRecordUntil(stopAt);
|
||||||
|
model.setRecordUntilSubsequentAction(action);
|
||||||
|
}
|
||||||
|
return confirmed;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,28 +2,51 @@ package ctbrec.ui;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import ctbrec.GlobalThreadPool;
|
import ctbrec.GlobalThreadPool;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.recorder.download.StreamSource;
|
import ctbrec.recorder.download.StreamSource;
|
||||||
import ctbrec.ui.controls.Dialogs;
|
import ctbrec.ui.controls.Dialogs;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
|
import javafx.concurrent.WorkerStateEvent;
|
||||||
|
import javafx.scene.Cursor;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.control.ButtonType;
|
||||||
import javafx.scene.control.ChoiceDialog;
|
import javafx.scene.control.ChoiceDialog;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
public class StreamSourceSelectionDialog {
|
public class StreamSourceSelectionDialog extends ChoiceDialog<StreamSource> {
|
||||||
private static final StreamSource BEST = new BestStreamSource();
|
|
||||||
|
|
||||||
private StreamSourceSelectionDialog() {
|
private static final Logger LOG = LoggerFactory.getLogger(StreamSourceSelectionDialog.class);
|
||||||
|
|
||||||
|
public static final StreamSource BEST = new BestStreamSource();
|
||||||
|
public static final StreamSource LOADING = new LoadingStreamSource();
|
||||||
|
private Scene parent;
|
||||||
|
private Model model;
|
||||||
|
private Task<List<StreamSource>> loadStreamSources;
|
||||||
|
|
||||||
|
|
||||||
|
public StreamSourceSelectionDialog(Scene parent, Model model) {
|
||||||
|
this.parent = parent;
|
||||||
|
this.model = model;
|
||||||
|
if (parent != null) {
|
||||||
|
getDialogPane().getScene().getStylesheets().addAll(parent.getStylesheets());
|
||||||
}
|
}
|
||||||
|
changeCursorTo(Cursor.WAIT);
|
||||||
public static void show(Scene parent, Model model, Consumer<Model> onSuccess, Consumer<Throwable> onFail) {
|
getItems().add(LOADING);
|
||||||
Task<List<StreamSource>> selectStreamSource = new Task<List<StreamSource>>() {
|
setSelectedItem(LOADING);
|
||||||
|
setTitle("Stream Quality");
|
||||||
|
setHeaderText("Select your preferred stream quality for " + model.getDisplayName());
|
||||||
|
var icon = Dialogs.class.getResourceAsStream("/icon.png");
|
||||||
|
var stage = (Stage) getDialogPane().getScene().getWindow();
|
||||||
|
stage.getIcons().add(new Image(icon));
|
||||||
|
setResultConverter(bt -> (bt == ButtonType.OK) ? getSelectedItem() : null);
|
||||||
|
loadStreamSources = new Task<List<StreamSource>>() {
|
||||||
@Override
|
@Override
|
||||||
protected List<StreamSource> call() throws Exception {
|
protected List<StreamSource> call() throws Exception {
|
||||||
List<StreamSource> sources = model.getStreamSources();
|
List<StreamSource> sources = model.getStreamSources();
|
||||||
|
@ -32,38 +55,56 @@ public class StreamSourceSelectionDialog {
|
||||||
return sources;
|
return sources;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
selectStreamSource.setOnSucceeded(e -> {
|
loadStreamSources.setOnFailed(this::onFailed);
|
||||||
|
loadStreamSources.setOnSucceeded(this::onSucceeded);
|
||||||
|
GlobalThreadPool.submit(loadStreamSources);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onFailed(WorkerStateEvent evt) {
|
||||||
|
changeCursorTo(Cursor.DEFAULT);
|
||||||
|
try {
|
||||||
|
loadStreamSources.get();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
LOG.error("Couldn't fetch available stream sources", e);
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
LOG.error("Couldn't fetch available stream sources", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean confirmed = Dialogs.showConfirmDialog("Error loading stream resolutions", "Do you want to add the model anyway?", "Stream resolutions unknown", parent);
|
||||||
|
if (confirmed) {
|
||||||
|
getItems().clear();
|
||||||
|
getItems().add(BEST);
|
||||||
|
setSelectedItem(BEST);
|
||||||
|
} else {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSucceeded(WorkerStateEvent evt) {
|
||||||
|
changeCursorTo(Cursor.DEFAULT);
|
||||||
List<StreamSource> sources;
|
List<StreamSource> sources;
|
||||||
try {
|
try {
|
||||||
sources = selectStreamSource.get();
|
sources = loadStreamSources.get();
|
||||||
|
getItems().remove(LOADING);
|
||||||
|
getItems().addAll(sources);
|
||||||
var selectedIndex = model.getStreamUrlIndex() > -1 ? Math.min(model.getStreamUrlIndex(), sources.size() - 1) : sources.size() - 1;
|
var selectedIndex = model.getStreamUrlIndex() > -1 ? Math.min(model.getStreamUrlIndex(), sources.size() - 1) : sources.size() - 1;
|
||||||
var choiceDialog = new ChoiceDialog<StreamSource>(sources.get(selectedIndex), sources);
|
setSelectedItem(getItems().get(selectedIndex));
|
||||||
choiceDialog.setTitle("Stream Quality");
|
} catch (InterruptedException e) {
|
||||||
choiceDialog.setHeaderText("Select your preferred stream quality for " + model.getDisplayName());
|
|
||||||
choiceDialog.setResizable(true);
|
|
||||||
var stage = (Stage) choiceDialog.getDialogPane().getScene().getWindow();
|
|
||||||
stage.getScene().getStylesheets().addAll(parent.getStylesheets());
|
|
||||||
var icon = Dialogs.class.getResourceAsStream("/icon.png");
|
|
||||||
stage.getIcons().add(new Image(icon));
|
|
||||||
Optional<StreamSource> selectedSource = choiceDialog.showAndWait();
|
|
||||||
if (selectedSource.isPresent()) {
|
|
||||||
int index = -1;
|
|
||||||
if (selectedSource.get() != BEST) {
|
|
||||||
index = sources.indexOf(selectedSource.get());
|
|
||||||
}
|
|
||||||
model.setStreamUrlIndex(index);
|
|
||||||
System.err.println(model + " " + model.getStreamUrlIndex());
|
|
||||||
onSuccess.accept(model);
|
|
||||||
}
|
|
||||||
} catch (ExecutionException e1) {
|
|
||||||
onFail.accept(e1);
|
|
||||||
} catch (InterruptedException e1) {
|
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
onFail.accept(e1);
|
showError(e);
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
showError(e);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
selectStreamSource.setOnFailed(e -> onFail.accept(selectStreamSource.getException()));
|
|
||||||
GlobalThreadPool.submit(selectStreamSource);
|
void changeCursorTo(Cursor cursor) {
|
||||||
|
parent.setCursor(cursor);
|
||||||
|
getDialogPane().setCursor(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showError(Exception e) {
|
||||||
|
Dialogs.showError(parent, getHeaderText(), getContentText(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class BestStreamSource extends StreamSource {
|
private static class BestStreamSource extends StreamSource {
|
||||||
|
@ -72,4 +113,19 @@ public class StreamSourceSelectionDialog {
|
||||||
return "Best";
|
return "Best";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class LoadingStreamSource extends StreamSource {
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Loading...";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int indexOf(StreamSource selectedSource) {
|
||||||
|
int index = -1;
|
||||||
|
if (selectedSource != LOADING && selectedSource != BEST) {
|
||||||
|
index = getItems().indexOf(selectedSource);
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,15 @@ public abstract class AbstractModelAction {
|
||||||
|
|
||||||
protected CompletableFuture<List<Result>> execute(String errorHeader, String errorMsg) {
|
protected CompletableFuture<List<Result>> execute(String errorHeader, String errorMsg) {
|
||||||
source.setCursor(Cursor.WAIT);
|
source.setCursor(Cursor.WAIT);
|
||||||
return CompletableFuture.supplyAsync(() -> {
|
return CompletableFuture.supplyAsync(() -> internalExecute(errorHeader, errorMsg), GlobalThreadPool.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CompletableFuture<List<Result>> executeSync(String errorHeader, String errorMsg) {
|
||||||
|
source.setCursor(Cursor.WAIT);
|
||||||
|
return CompletableFuture.completedFuture(internalExecute(errorHeader, errorMsg));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<Result> internalExecute(String errorHeader, String errorMsg) {
|
||||||
final List<Result> result = new ArrayList<>(models.size());
|
final List<Result> result = new ArrayList<>(models.size());
|
||||||
final List<CompletableFuture<Model>> futures = new ArrayList<>(models.size());
|
final List<CompletableFuture<Model>> futures = new ArrayList<>(models.size());
|
||||||
for (Model model : models) {
|
for (Model model : models) {
|
||||||
|
@ -41,6 +49,11 @@ public abstract class AbstractModelAction {
|
||||||
result.add(new Result(model, ex))));
|
result.add(new Result(model, ex))));
|
||||||
}
|
}
|
||||||
Platform.runLater(() -> source.setCursor(Cursor.DEFAULT));
|
Platform.runLater(() -> source.setCursor(Cursor.DEFAULT));
|
||||||
|
checkResultForErrors(errorHeader, errorMsg, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void checkResultForErrors(String errorHeader, String errorMsg, List<Result> result) {
|
||||||
List<Result> failed = result.stream().filter(Result::failed).collect(Collectors.toList());
|
List<Result> failed = result.stream().filter(Result::failed).collect(Collectors.toList());
|
||||||
if (!failed.isEmpty()) {
|
if (!failed.isEmpty()) {
|
||||||
Throwable t = failed.get(0).getThrowable();
|
Throwable t = failed.get(0).getThrowable();
|
||||||
|
@ -48,8 +61,6 @@ public abstract class AbstractModelAction {
|
||||||
String msg = MessageFormat.format(errorMsg, failedModelList);
|
String msg = MessageFormat.format(errorMsg, failedModelList);
|
||||||
Dialogs.showError(source.getScene(), errorHeader, msg, t);
|
Dialogs.showError(source.getScene(), errorHeader, msg, t);
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}, GlobalThreadPool.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Result {
|
public static class Result {
|
||||||
|
|
|
@ -1,13 +1,8 @@
|
||||||
package ctbrec.ui.action;
|
package ctbrec.ui.action;
|
||||||
|
|
||||||
import static ctbrec.SubsequentAction.*;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.time.Instant;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.time.ZoneId;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -15,20 +10,13 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import ctbrec.GlobalThreadPool;
|
import ctbrec.GlobalThreadPool;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.SubsequentAction;
|
|
||||||
import ctbrec.recorder.Recorder;
|
import ctbrec.recorder.Recorder;
|
||||||
import ctbrec.ui.controls.DateTimePicker;
|
import ctbrec.ui.RecordUntilDialog;
|
||||||
import ctbrec.ui.controls.Dialogs;
|
import ctbrec.ui.controls.Dialogs;
|
||||||
import ctbrec.ui.tasks.StartRecordingTask;
|
import ctbrec.ui.tasks.StartRecordingTask;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.geometry.Insets;
|
|
||||||
import javafx.scene.Cursor;
|
import javafx.scene.Cursor;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.Label;
|
|
||||||
import javafx.scene.control.RadioButton;
|
|
||||||
import javafx.scene.control.ToggleGroup;
|
|
||||||
import javafx.scene.layout.GridPane;
|
|
||||||
import javafx.scene.layout.HBox;
|
|
||||||
|
|
||||||
public class SetStopDateAction {
|
public class SetStopDateAction {
|
||||||
|
|
||||||
|
@ -38,9 +26,6 @@ public class SetStopDateAction {
|
||||||
private Model model;
|
private Model model;
|
||||||
private Recorder recorder;
|
private Recorder recorder;
|
||||||
|
|
||||||
private RadioButton pauseButton;
|
|
||||||
private DateTimePicker datePicker;
|
|
||||||
|
|
||||||
public SetStopDateAction(Node source, Model model, Recorder recorder) {
|
public SetStopDateAction(Node source, Model model, Recorder recorder) {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.model = model;
|
this.model = model;
|
||||||
|
@ -49,31 +34,8 @@ public class SetStopDateAction {
|
||||||
|
|
||||||
public CompletableFuture<Boolean> execute() {
|
public CompletableFuture<Boolean> execute() {
|
||||||
source.setCursor(Cursor.WAIT);
|
source.setCursor(Cursor.WAIT);
|
||||||
datePicker = new DateTimePicker();
|
RecordUntilDialog dialog = new RecordUntilDialog(source, model);
|
||||||
var gridPane = new GridPane();
|
boolean userClickedOk = dialog.showAndWait();
|
||||||
gridPane.setHgap(10);
|
|
||||||
gridPane.setVgap(10);
|
|
||||||
gridPane.setPadding(new Insets(20, 150, 10, 10));
|
|
||||||
gridPane.add(new Label("Stop at"), 0, 0);
|
|
||||||
gridPane.add(datePicker, 1, 0);
|
|
||||||
gridPane.add(new Label("And then"), 0, 1);
|
|
||||||
var toggleGroup = new ToggleGroup();
|
|
||||||
pauseButton = new RadioButton("pause recording");
|
|
||||||
pauseButton.setSelected(model.getRecordUntilSubsequentAction() == PAUSE);
|
|
||||||
pauseButton.setToggleGroup(toggleGroup);
|
|
||||||
var removeButton = new RadioButton("remove model");
|
|
||||||
removeButton.setSelected(model.getRecordUntilSubsequentAction() == REMOVE);
|
|
||||||
removeButton.setToggleGroup(toggleGroup);
|
|
||||||
var row = new HBox();
|
|
||||||
row.getChildren().addAll(pauseButton, removeButton);
|
|
||||||
HBox.setMargin(pauseButton, new Insets(5));
|
|
||||||
HBox.setMargin(removeButton, new Insets(5));
|
|
||||||
gridPane.add(row, 1, 1);
|
|
||||||
if (model.isRecordingTimeLimited()) {
|
|
||||||
var localDate = LocalDateTime.ofInstant(model.getRecordUntil(), ZoneId.systemDefault());
|
|
||||||
datePicker.setDateTimeValue(localDate);
|
|
||||||
}
|
|
||||||
boolean userClickedOk = Dialogs.showCustomInput(source.getScene(), "Stop Recording of " + model.getDisplayName() + " at", gridPane);
|
|
||||||
return createAsyncTask(userClickedOk);
|
return createAsyncTask(userClickedOk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,11 +54,6 @@ public class SetStopDateAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setRecordingTimeLimit() {
|
private void setRecordingTimeLimit() {
|
||||||
SubsequentAction action = pauseButton.isSelected() ? PAUSE : REMOVE;
|
|
||||||
LOG.info("Stop at {} and {}", datePicker.getDateTimeValue(), action);
|
|
||||||
var stopAt = Instant.from(datePicker.getDateTimeValue().atZone(ZoneId.systemDefault()));
|
|
||||||
model.setRecordUntil(stopAt);
|
|
||||||
model.setRecordUntilSubsequentAction(action);
|
|
||||||
try {
|
try {
|
||||||
if (!recorder.isTracked(model) || model.isMarkedForLaterRecording()) {
|
if (!recorder.isTracked(model) || model.isMarkedForLaterRecording()) {
|
||||||
new StartRecordingTask(recorder).executeSync(model)
|
new StartRecordingTask(recorder).executeSync(model)
|
||||||
|
|
|
@ -1,20 +1,78 @@
|
||||||
package ctbrec.ui.action;
|
package ctbrec.ui.action;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
import ctbrec.Config;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.recorder.Recorder;
|
import ctbrec.recorder.Recorder;
|
||||||
|
import ctbrec.recorder.download.StreamSource;
|
||||||
|
import ctbrec.ui.RecordUntilDialog;
|
||||||
|
import ctbrec.ui.StreamSourceSelectionDialog;
|
||||||
import ctbrec.ui.tasks.StartRecordingTask;
|
import ctbrec.ui.tasks.StartRecordingTask;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.scene.Cursor;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
|
|
||||||
public class StartRecordingAction extends AbstractModelAction {
|
public class StartRecordingAction extends AbstractModelAction {
|
||||||
|
|
||||||
|
private static final String ERROR_HEADER = "Couldn't start recording";
|
||||||
|
private static final String ERROR_MSG = "Starting recording of {0} failed:";
|
||||||
|
|
||||||
|
private boolean showRecordUntilDialog = false;
|
||||||
|
|
||||||
public StartRecordingAction(Node source, List<Model> models, Recorder recorder) {
|
public StartRecordingAction(Node source, List<Model> models, Recorder recorder) {
|
||||||
super(source, models, recorder, new StartRecordingTask(recorder));
|
super(source, models, recorder, new StartRecordingTask(recorder));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public StartRecordingAction showRecordUntilDialog() {
|
||||||
|
showRecordUntilDialog = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public CompletableFuture<List<Result>> execute() {
|
public CompletableFuture<List<Result>> execute() {
|
||||||
return super.execute("Couldn't start recording", "Starting recording of {0} failed:");
|
boolean selectSource = Config.getInstance().getSettings().chooseStreamQuality;
|
||||||
|
if (selectSource || showRecordUntilDialog) {
|
||||||
|
var future = executeSync();
|
||||||
|
Platform.runLater(() -> source.setCursor(Cursor.DEFAULT));
|
||||||
|
return future;
|
||||||
|
} else {
|
||||||
|
return super.execute(ERROR_HEADER, ERROR_MSG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CompletableFuture<List<Result>> executeSync() {
|
||||||
|
var result = new ArrayList<Result>(models.size());
|
||||||
|
for (final Model model : models) {
|
||||||
|
if (showRecordUntilDialog) {
|
||||||
|
RecordUntilDialog dialog = new RecordUntilDialog(source, model);
|
||||||
|
var confirmed = dialog.showAndWait();
|
||||||
|
if (!confirmed) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean selectSource = Config.getInstance().getSettings().chooseStreamQuality;
|
||||||
|
if (selectSource) {
|
||||||
|
var dialog = new StreamSourceSelectionDialog(source.getScene(), model);
|
||||||
|
Optional<StreamSource> selection = dialog.showAndWait();
|
||||||
|
if (selection.isPresent()) {
|
||||||
|
StreamSource src = selection.get();
|
||||||
|
if (src != StreamSourceSelectionDialog.LOADING) {
|
||||||
|
int index = dialog.indexOf(src);
|
||||||
|
model.setStreamUrlIndex(index);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new StartRecordingTask(recorder).executeSync(model)
|
||||||
|
.whenComplete((mdl, ex) -> result.add(new Result(mdl, ex)));
|
||||||
|
}
|
||||||
|
checkResultForErrors(ERROR_HEADER, ERROR_MSG, result);
|
||||||
|
return CompletableFuture.completedFuture(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import ctbrec.Config;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.ModelGroup;
|
import ctbrec.ModelGroup;
|
||||||
import ctbrec.recorder.Recorder;
|
import ctbrec.recorder.Recorder;
|
||||||
|
import ctbrec.recorder.download.StreamSource;
|
||||||
import ctbrec.ui.AutosizeAlert;
|
import ctbrec.ui.AutosizeAlert;
|
||||||
import ctbrec.ui.DesktopIntegration;
|
import ctbrec.ui.DesktopIntegration;
|
||||||
import ctbrec.ui.StreamSourceSelectionDialog;
|
import ctbrec.ui.StreamSourceSelectionDialog;
|
||||||
|
@ -34,6 +35,8 @@ import ctbrec.ui.action.TipAction;
|
||||||
import ctbrec.ui.action.TriConsumer;
|
import ctbrec.ui.action.TriConsumer;
|
||||||
import ctbrec.ui.controls.Dialogs;
|
import ctbrec.ui.controls.Dialogs;
|
||||||
import ctbrec.ui.tabs.FollowedTab;
|
import ctbrec.ui.tabs.FollowedTab;
|
||||||
|
import javafx.event.ActionEvent;
|
||||||
|
import javafx.event.EventHandler;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.Alert;
|
import javafx.scene.control.Alert;
|
||||||
import javafx.scene.control.ContextMenu;
|
import javafx.scene.control.ContextMenu;
|
||||||
|
@ -47,9 +50,6 @@ public class ModelMenuContributor {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ModelMenuContributor.class);
|
private static final Logger LOG = LoggerFactory.getLogger(ModelMenuContributor.class);
|
||||||
|
|
||||||
private static final String COULDNT_START_STOP_RECORDING = "Couldn't start/stop recording";
|
|
||||||
private static final String ERROR = "Error";
|
|
||||||
|
|
||||||
private Config config;
|
private Config config;
|
||||||
private Recorder recorder;
|
private Recorder recorder;
|
||||||
private Node source;
|
private Node source;
|
||||||
|
@ -242,8 +242,8 @@ public class ModelMenuContributor {
|
||||||
var couldntSwitchHeaderText = "Couldn't switch stream resolution";
|
var couldntSwitchHeaderText = "Couldn't switch stream resolution";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!selectedModel.isOnline(true)) {
|
if (!selectedModel.isOnline()) {
|
||||||
Dialogs.showError(source.getScene(), couldntSwitchHeaderText, "The resolution can only be changed, when the model is online", null);
|
Dialogs.showError(source.getScene(), couldntSwitchHeaderText, "The resolution can only be changed when the model is online", null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e1) {
|
} catch (InterruptedException e1) {
|
||||||
|
@ -255,19 +255,21 @@ public class ModelMenuContributor {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Consumer<Model> onSuccess = m -> {
|
StreamSourceSelectionDialog dialog = new StreamSourceSelectionDialog(source.getScene(), selectedModel);
|
||||||
|
Optional<StreamSource> selectedSource = dialog.showAndWait();
|
||||||
|
if (selectedSource.isPresent()) {
|
||||||
|
StreamSource src = selectedSource.get();
|
||||||
|
if (src != StreamSourceSelectionDialog.LOADING) {
|
||||||
|
int index = dialog.indexOf(selectedSource.get());
|
||||||
|
selectedModel.setStreamUrlIndex(index);
|
||||||
try {
|
try {
|
||||||
recorder.switchStreamSource(m);
|
recorder.switchStreamSource(selectedModel);
|
||||||
} catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException | IOException e) {
|
} catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException | IOException e) {
|
||||||
LOG.error(couldntSwitchHeaderText, e);
|
LOG.error(couldntSwitchHeaderText, e);
|
||||||
showStreamSwitchErrorDialog(e);
|
showStreamSwitchErrorDialog(e);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
Consumer<Throwable> onFail = t -> {
|
}
|
||||||
LOG.error(couldntSwitchHeaderText, t);
|
|
||||||
showStreamSwitchErrorDialog(t);
|
|
||||||
};
|
|
||||||
StreamSourceSelectionDialog.show(source.getScene(), selectedModel, onSuccess, onFail);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showStreamSwitchErrorDialog(Throwable throwable) {
|
private void showStreamSwitchErrorDialog(Throwable throwable) {
|
||||||
|
@ -343,13 +345,28 @@ public class ModelMenuContributor {
|
||||||
|
|
||||||
private void addStartRecordingWithTimeLimit(ContextMenu menu, List<Model> selectedModels) {
|
private void addStartRecordingWithTimeLimit(ContextMenu menu, List<Model> selectedModels) {
|
||||||
var model = selectedModels.get(0);
|
var model = selectedModels.get(0);
|
||||||
var text = recorder.isTracked(model) ? "Record Until" : "Start Recording Until";
|
String text;
|
||||||
|
EventHandler<ActionEvent> eventHandler;
|
||||||
|
if (recorder.isTracked(model)) {
|
||||||
|
text = "Record Until";
|
||||||
|
eventHandler = e -> {
|
||||||
|
for (Model selectedModel : selectedModels) {
|
||||||
|
new SetStopDateAction(source, selectedModel, recorder)
|
||||||
|
.execute()
|
||||||
|
.thenAccept(r -> executeCallback());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
text = "Start Recording Until";
|
||||||
|
eventHandler = e -> new StartRecordingAction(source, selectedModels, recorder)
|
||||||
|
.showRecordUntilDialog()
|
||||||
|
.execute()
|
||||||
|
.thenAccept(r -> executeCallback());
|
||||||
|
}
|
||||||
|
|
||||||
var start = new MenuItem(text);
|
var start = new MenuItem(text);
|
||||||
|
start.setOnAction(eventHandler);
|
||||||
menu.getItems().add(start);
|
menu.getItems().add(start);
|
||||||
start.setOnAction(e -> {
|
|
||||||
selectedModels.forEach(m -> new SetStopDateAction(source, m, recorder).execute() //
|
|
||||||
.thenAccept(b -> executeCallback()));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addRemoveTimeLimit(ContextMenu menu, List<Model> selectedModels) {
|
private void addRemoveTimeLimit(ContextMenu menu, List<Model> selectedModels) {
|
||||||
|
@ -395,22 +412,22 @@ public class ModelMenuContributor {
|
||||||
|
|
||||||
private void startStopAction(List<Model> selection, boolean start) {
|
private void startStopAction(List<Model> selection, boolean start) {
|
||||||
if (start) {
|
if (start) {
|
||||||
boolean selectSource = Config.getInstance().getSettings().chooseStreamQuality;
|
// boolean selectSource = Config.getInstance().getSettings().chooseStreamQuality;
|
||||||
if (selectSource) {
|
// if (selectSource) {
|
||||||
for (Model model : selection) {
|
// for (Model model : selection) {
|
||||||
Consumer<Model> onSuccess = modl -> startRecording(List.of(modl));
|
// Consumer<Model> onSuccess = modl -> startRecording(List.of(modl));
|
||||||
Consumer<Throwable> onFail = throwable -> {
|
// Consumer<Throwable> onFail = throwable -> {
|
||||||
Alert alert = new AutosizeAlert(Alert.AlertType.ERROR, source.getScene());
|
// Alert alert = new AutosizeAlert(Alert.AlertType.ERROR, source.getScene());
|
||||||
alert.setTitle(ERROR);
|
// alert.setTitle(ERROR);
|
||||||
alert.setHeaderText(COULDNT_START_STOP_RECORDING);
|
// alert.setHeaderText(COULDNT_START_STOP_RECORDING);
|
||||||
alert.setContentText("I/O error while starting/stopping the recording: " + throwable.getLocalizedMessage());
|
// alert.setContentText("I/O error while starting/stopping the recording: " + throwable.getLocalizedMessage());
|
||||||
alert.showAndWait();
|
// alert.showAndWait();
|
||||||
};
|
// };
|
||||||
StreamSourceSelectionDialog.show(source.getScene(), model, onSuccess, onFail);
|
// StreamSourceSelectionDialog.show(source.getScene(), model, onSuccess, onFail);
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
|
// }
|
||||||
startRecording(selection);
|
startRecording(selection);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
stopRecording(selection);
|
stopRecording(selection);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,12 @@ import static ctbrec.io.HttpConstants.*;
|
||||||
import static ctbrec.ui.Icon.*;
|
import static ctbrec.ui.Icon.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -29,9 +29,10 @@ import ctbrec.ui.AutosizeAlert;
|
||||||
import ctbrec.ui.CamrecApplication;
|
import ctbrec.ui.CamrecApplication;
|
||||||
import ctbrec.ui.Icon;
|
import ctbrec.ui.Icon;
|
||||||
import ctbrec.ui.SiteUiFactory;
|
import ctbrec.ui.SiteUiFactory;
|
||||||
import ctbrec.ui.StreamSourceSelectionDialog;
|
|
||||||
import ctbrec.ui.action.EditGroupAction;
|
import ctbrec.ui.action.EditGroupAction;
|
||||||
import ctbrec.ui.action.PlayAction;
|
import ctbrec.ui.action.PlayAction;
|
||||||
|
import ctbrec.ui.action.StartRecordingAction;
|
||||||
|
import ctbrec.ui.action.StopRecordingAction;
|
||||||
import ctbrec.ui.controls.Dialogs;
|
import ctbrec.ui.controls.Dialogs;
|
||||||
import ctbrec.ui.controls.RecordingIndicator;
|
import ctbrec.ui.controls.RecordingIndicator;
|
||||||
import ctbrec.ui.controls.StreamPreview;
|
import ctbrec.ui.controls.StreamPreview;
|
||||||
|
@ -70,7 +71,6 @@ import okhttp3.Response;
|
||||||
|
|
||||||
public class ThumbCell extends StackPane {
|
public class ThumbCell extends StackPane {
|
||||||
|
|
||||||
private static final String COULDNT_START_STOP_RECORDING = "Couldn't start/stop recording";
|
|
||||||
private static final String ERROR = "Error";
|
private static final String ERROR = "Error";
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ThumbCell.class);
|
private static final Logger LOG = LoggerFactory.getLogger(ThumbCell.class);
|
||||||
private static final Duration ANIMATION_DURATION = new Duration(250);
|
private static final Duration ANIMATION_DURATION = new Duration(250);
|
||||||
|
@ -261,12 +261,18 @@ public class ThumbCell extends StackPane {
|
||||||
pauseResumeAction(false);
|
pauseResumeAction(false);
|
||||||
break;
|
break;
|
||||||
case BOOKMARKED:
|
case BOOKMARKED:
|
||||||
recordLater(false);
|
forgetModel();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void forgetModel() {
|
||||||
|
new StopRecordingAction(this, List.of(model), recorder)
|
||||||
|
.execute()
|
||||||
|
.thenAccept(r -> update());
|
||||||
|
}
|
||||||
|
|
||||||
private Node createPreviewTrigger() {
|
private Node createPreviewTrigger() {
|
||||||
var s = 24;
|
var s = 24;
|
||||||
previewTrigger = new StackPane();
|
previewTrigger = new StackPane();
|
||||||
|
@ -514,21 +520,10 @@ public class ThumbCell extends StackPane {
|
||||||
}
|
}
|
||||||
|
|
||||||
void startStopAction(boolean start) {
|
void startStopAction(boolean start) {
|
||||||
setCursor(Cursor.WAIT);
|
if (start) {
|
||||||
|
new StartRecordingAction(this, List.of(getModel()), recorder).execute();
|
||||||
boolean selectSource = Config.getInstance().getSettings().chooseStreamQuality;
|
|
||||||
if (selectSource && start) {
|
|
||||||
Consumer<Model> onSuccess = modl -> startStopActionAsync(modl, true);
|
|
||||||
Consumer<Throwable> onFail = throwable -> {
|
|
||||||
Alert alert = new AutosizeAlert(Alert.AlertType.ERROR, getScene());
|
|
||||||
alert.setTitle(ERROR);
|
|
||||||
alert.setHeaderText(COULDNT_START_STOP_RECORDING);
|
|
||||||
alert.setContentText("I/O error while starting/stopping the recording: " + throwable.getLocalizedMessage());
|
|
||||||
alert.showAndWait();
|
|
||||||
};
|
|
||||||
StreamSourceSelectionDialog.show(getScene(), model, onSuccess, onFail);
|
|
||||||
} else {
|
} else {
|
||||||
startStopActionAsync(model, start);
|
new StopRecordingAction(this, List.of(getModel()), recorder).execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,26 +552,6 @@ public class ThumbCell extends StackPane {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startStopActionAsync(Model model, boolean start) {
|
|
||||||
GlobalThreadPool.submit(() -> {
|
|
||||||
try {
|
|
||||||
if (start) {
|
|
||||||
recorder.addModel(model);
|
|
||||||
setRecording(!model.isMarkedForLaterRecording());
|
|
||||||
} else {
|
|
||||||
recorder.stopRecording(model);
|
|
||||||
setRecording(false);
|
|
||||||
}
|
|
||||||
update();
|
|
||||||
} catch (Exception e1) {
|
|
||||||
LOG.error(COULDNT_START_STOP_RECORDING, e1);
|
|
||||||
Dialogs.showError(getScene(), COULDNT_START_STOP_RECORDING, "I/O error while starting/stopping the recording: ", e1);
|
|
||||||
} finally {
|
|
||||||
Platform.runLater(() -> setCursor(Cursor.DEFAULT));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
CompletableFuture<Boolean> follow(boolean follow) {
|
CompletableFuture<Boolean> follow(boolean follow) {
|
||||||
setCursor(Cursor.WAIT);
|
setCursor(Cursor.WAIT);
|
||||||
return CompletableFuture.supplyAsync(() -> {
|
return CompletableFuture.supplyAsync(() -> {
|
||||||
|
@ -612,11 +587,6 @@ public class ThumbCell extends StackPane {
|
||||||
}, GlobalThreadPool.get());
|
}, GlobalThreadPool.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void recordLater(boolean recordLater) {
|
|
||||||
model.setMarkedForLaterRecording(recordLater);
|
|
||||||
startStopAction(recordLater);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Model getModel() {
|
public Model getModel() {
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,6 @@ package ctbrec.ui.tabs.recorded;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.InvalidKeyException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
@ -32,8 +29,10 @@ import ctbrec.ui.AutosizeAlert;
|
||||||
import ctbrec.ui.JavaFxModel;
|
import ctbrec.ui.JavaFxModel;
|
||||||
import ctbrec.ui.PreviewPopupHandler;
|
import ctbrec.ui.PreviewPopupHandler;
|
||||||
import ctbrec.ui.action.AbstractPortraitAction.PortraitChangedEvent;
|
import ctbrec.ui.action.AbstractPortraitAction.PortraitChangedEvent;
|
||||||
|
import ctbrec.ui.action.MarkForLaterRecordingAction;
|
||||||
import ctbrec.ui.action.PlayAction;
|
import ctbrec.ui.action.PlayAction;
|
||||||
import ctbrec.ui.action.SetPortraitAction;
|
import ctbrec.ui.action.SetPortraitAction;
|
||||||
|
import ctbrec.ui.action.StartRecordingAction;
|
||||||
import ctbrec.ui.controls.CustomMouseBehaviorContextMenu;
|
import ctbrec.ui.controls.CustomMouseBehaviorContextMenu;
|
||||||
import ctbrec.ui.controls.Dialogs;
|
import ctbrec.ui.controls.Dialogs;
|
||||||
import ctbrec.ui.controls.SearchBox;
|
import ctbrec.ui.controls.SearchBox;
|
||||||
|
@ -109,9 +108,11 @@ public abstract class AbstractRecordedModelsTab extends Tab implements TabSelect
|
||||||
protected ScrollPane scrollPane = new ScrollPane();
|
protected ScrollPane scrollPane = new ScrollPane();
|
||||||
protected ContextMenu popup;
|
protected ContextMenu popup;
|
||||||
|
|
||||||
|
protected Config config;
|
||||||
|
|
||||||
AbstractRecordedModelsTab(String text) {
|
AbstractRecordedModelsTab(String text) {
|
||||||
super(text);
|
super(text);
|
||||||
|
config = Config.getInstance();
|
||||||
registerPortraitListener();
|
registerPortraitListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,11 +348,10 @@ public abstract class AbstractRecordedModelsTab extends Tab implements TabSelect
|
||||||
for (Site site : sites) {
|
for (Site site : sites) {
|
||||||
var newModel = site.createModelFromUrl(url);
|
var newModel = site.createModelFromUrl(url);
|
||||||
if (newModel != null) {
|
if (newModel != null) {
|
||||||
try {
|
if (getMarkModelsForLaterRecording()) {
|
||||||
newModel.setMarkedForLaterRecording(getMarkModelsForLaterRecording());
|
new MarkForLaterRecordingAction(getTabPane(), List.of(newModel), true, recorder).execute();
|
||||||
recorder.addModel(newModel);
|
} else {
|
||||||
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e1) {
|
new StartRecordingAction(getTabPane(), List.of(newModel), recorder).execute();
|
||||||
Dialogs.showError(getTabPane().getScene(), "Couldn't add model", "The model " + newModel.getName() + " could not be added: ", e1);
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -374,12 +374,11 @@ public abstract class AbstractRecordedModelsTab extends Tab implements TabSelect
|
||||||
String modelName = parts[1];
|
String modelName = parts[1];
|
||||||
for (Site site : sites) {
|
for (Site site : sites) {
|
||||||
if (Objects.equals(siteName.toLowerCase(), site.getClass().getSimpleName().toLowerCase())) {
|
if (Objects.equals(siteName.toLowerCase(), site.getClass().getSimpleName().toLowerCase())) {
|
||||||
try {
|
var newModel = site.createModel(modelName);
|
||||||
var m = site.createModel(modelName);
|
if (getMarkModelsForLaterRecording()) {
|
||||||
m.setMarkedForLaterRecording(getMarkModelsForLaterRecording());
|
new MarkForLaterRecordingAction(getTabPane(), List.of(newModel), true, recorder).execute();
|
||||||
recorder.addModel(m);
|
} else {
|
||||||
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e1) {
|
new StartRecordingAction(getTabPane(), List.of(newModel), recorder).execute();
|
||||||
Dialogs.showError(getTabPane().getScene(), "Couldn't add model", "The model " + modelName + " could not be added:", e1);
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue