Use ModelMenuContributor for context menu on the RecordedModelsTab

This commit is contained in:
0xb00bface 2021-07-18 14:00:38 +02:00
parent ebc8d4b321
commit 31c9a38d06
6 changed files with 173 additions and 208 deletions

View File

@ -30,13 +30,13 @@ import javafx.scene.layout.Region;
public class AddToGroupAction {
private Node source;
private Model model;
private List<Model> models;
private Recorder recorder;
public AddToGroupAction(Node source, Recorder recorder, Model model) {
public AddToGroupAction(Node source, Recorder recorder, List<Model> models) {
this.source = source;
this.recorder = recorder;
this.model = model;
this.models = models;
}
public void execute() {
@ -56,13 +56,17 @@ public class AddToGroupAction {
Set<ModelGroup> modelGroups = recorder.getModelGroups();
Optional<ModelGroup> existingGroup = modelGroups.stream().filter(mg -> mg.getName().equalsIgnoreCase(text)).findFirst();
if (existingGroup.isPresent()) {
existingGroup.get().add(model);
for (Model model : models) {
existingGroup.get().add(model);
}
recorder.saveModelGroup(existingGroup.get());
} else {
var group = new ModelGroup();
group.setId(UUID.randomUUID());
group.setName(text);
group.add(model);
for (Model model : models) {
group.add(model);
}
modelGroups.add(group);
recorder.saveModelGroup(group);
}
@ -122,7 +126,7 @@ public class AddToGroupAction {
}
private void suggestInitialName(Set<ModelGroup> modelGroups) {
String bestName = model.getDisplayName();
String bestName = models.get(0).getDisplayName();
for (ModelGroup modelGroup : modelGroups) {
if (StringUtil.percentageOfEquality(bestName, modelGroup.getName()) > 70) {
bestName = modelGroup.getName();

View File

@ -8,23 +8,21 @@ import org.slf4j.LoggerFactory;
import ctbrec.Config;
import ctbrec.Model;
import ctbrec.ui.JavaFxModel;
import ctbrec.ui.controls.Dialogs;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.control.TableView;
public class EditNotesAction {
private static final Logger LOG = LoggerFactory.getLogger(EditNotesAction.class);
private Node source;
private Model model;
private TableView<JavaFxModel> table;
private Runnable callback;
public EditNotesAction(Node source, Model selectedModel, TableView<JavaFxModel> table) {
public EditNotesAction(Node source, Model selectedModel, Runnable callback) {
this.source = source;
this.model = selectedModel;
this.table = table;
this.callback = callback;
}
public void execute() {
@ -43,7 +41,13 @@ public class EditNotesAction {
LOG.warn("Couldn't save config", e);
}
});
table.refresh();
if (callback != null) {
try {
callback.run();
} catch (Exception e) {
LOG.error("Error while executing callback", e);
}
}
source.setCursor(Cursor.DEFAULT);
}
}

View File

@ -77,6 +77,12 @@ public class SetStopDateAction {
model.setRecordUntil(stopAt);
model.setRecordUntilSubsequentAction(action);
try {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
recorder.stopRecordingAt(model);
} catch (InvalidKeyException | NoSuchAlgorithmException | IOException e) {
Dialogs.showError(source.getScene(), "Error", "Couln't set stop date", e);

View File

@ -1,8 +1,12 @@
package ctbrec.ui.menu;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
import org.slf4j.Logger;
@ -18,9 +22,11 @@ import ctbrec.ui.DesktopIntegration;
import ctbrec.ui.SiteUiFactory;
import ctbrec.ui.StreamSourceSelectionDialog;
import ctbrec.ui.action.AddToGroupAction;
import ctbrec.ui.action.EditNotesAction;
import ctbrec.ui.action.IgnoreModelsAction;
import ctbrec.ui.action.OpenRecordingsDir;
import ctbrec.ui.action.PlayAction;
import ctbrec.ui.action.RemoveTimeLimitAction;
import ctbrec.ui.action.SetStopDateAction;
import ctbrec.ui.action.StartRecordingAction;
import ctbrec.ui.action.StopRecordingAction;
@ -35,6 +41,7 @@ import javafx.scene.control.Alert;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.control.TabPane;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
@ -52,6 +59,7 @@ public class ModelMenuContributor {
private TriConsumer<Model, Boolean, Boolean> followCallback;
private Consumer<Model> ignoreCallback;
private boolean removeWithIgnore = false;
private Runnable callback;
private ModelMenuContributor(Node source, Config config, Recorder recorder) {
this.source = source;
@ -87,21 +95,39 @@ public class ModelMenuContributor {
startStopCallback = Optional.ofNullable(startStopCallback).orElse(m -> {});
followCallback = Optional.ofNullable(followCallback).orElse((m, f, s) -> {});
ignoreCallback = Optional.ofNullable(ignoreCallback).orElse(m -> {});
callback = Optional.ofNullable(callback).orElse(() -> {});
addOpenInPlayer(menu, selectedModels);
addOpenInBrowser(menu, selectedModels);
addCopyUrl(menu, selectedModels);
menu.getItems().add(new SeparatorMenuItem());
addStartOrStop(menu, selectedModels);
addStartRecordingWithTimeLimit(menu, selectedModels);
addRemoveTimeLimit(menu, selectedModels);
addSwitchStreamSource(menu, selectedModels);
addStartPaused(menu, selectedModels);
addRecordLater(menu, selectedModels);
addPauseResume(menu, selectedModels);
addGroupMenu(menu, selectedModels);
menu.getItems().add(new SeparatorMenuItem());
addFollowUnfollow(menu, selectedModels);
addSendTip(menu, selectedModels);
addIgnore(menu, selectedModels);
addOpenRecDir(menu, selectedModels);
addNotes(menu, selectedModels);
}
public ModelMenuContributor afterwards(Runnable callback) {
this.callback = callback;
return this;
}
private void addNotes(ContextMenu menu, List<Model> selectedModels) {
var notes = new MenuItem("Notes");
notes.setDisable(selectedModels.size() != 1);
notes.setOnAction(e -> new EditNotesAction(source, selectedModels.get(0), callback).execute());
menu.getItems().add(notes);
}
private void addOpenRecDir(ContextMenu menu, List<Model> selectedModels) {
@ -110,7 +136,11 @@ public class ModelMenuContributor {
}
var model = selectedModels.get(0);
var openRecDir = new MenuItem("Open recording directory");
openRecDir.setOnAction(e -> new OpenRecordingsDir(source, model).execute());
openRecDir.setDisable(selectedModels.size() != 1);
openRecDir.setOnAction(e -> {
new OpenRecordingsDir(source, model).execute();
executeCallback();
});
menu.getItems().add(openRecDir);
}
@ -124,26 +154,28 @@ public class ModelMenuContributor {
if (selectedModels == null || selectedModels.isEmpty()) {
return;
}
var model = selectedModels.get(0);
var copyUrl = new MenuItem("Copy URL");
copyUrl.setOnAction(e -> {
var sb = new StringBuilder();
for (Model model : selectedModels) {
sb.append(model.getUrl()).append('\n');
}
sb.deleteCharAt(sb.length() - 1);
final var content = new ClipboardContent();
content.putString(model.getUrl());
content.putString(sb.toString());
Clipboard.getSystemClipboard().setContent(content);
});
menu.getItems().add(copyUrl);
}
private void addSendTip(ContextMenu menu, List<Model> selectedModels) {
if (selectedModels == null || selectedModels.isEmpty()) {
return;
}
var model = selectedModels.get(0);
var site = model.getSite();
if (site.supportsTips()) {
var sendTip = new MenuItem("Send Tip");
sendTip.setOnAction(e -> new TipAction(model, source).execute());
sendTip.setDisable(!site.credentialsAvailable());
sendTip.setDisable(selectedModels.size() != 1);
menu.getItems().add(sendTip);
}
}
@ -166,13 +198,21 @@ public class ModelMenuContributor {
var unfollow = new MenuItem("Unfollow");
unfollow.setOnAction(e -> follow(selectedModels, false));
var followOrUnFollow = (source instanceof FollowedTab) ? unfollow : follow; // TODO source instanceof FollowedTab does not work
var followOrUnFollow = isFollowedTab() ? unfollow : follow;
followOrUnFollow.setDisable(!site.credentialsAvailable());
menu.getItems().add(followOrUnFollow);
followOrUnFollow.setDisable(!site.credentialsAvailable());
}
}
private boolean isFollowedTab() {
if (source instanceof TabPane) {
var tabPane = (TabPane) source;
return tabPane.getSelectionModel().getSelectedItem() instanceof FollowedTab;
}
return false;
}
protected void follow(List<Model> selectedModels, boolean follow) {
for (Model model : selectedModels) {
follow(model, follow);
@ -219,11 +259,71 @@ public class ModelMenuContributor {
}, GlobalThreadPool.get());
}
private void addSwitchStreamSource(ContextMenu menu, List<Model> selectedModels) {
var model = selectedModels.get(0);
if (!recorder.isTracked(model)) {
return;
}
var switchStreamSource = new MenuItem("Switch resolution");
switchStreamSource.setOnAction(e -> switchStreamSource(selectedModels.get(0)));
menu.getItems().add(switchStreamSource);
switchStreamSource.setDisable(selectedModels.size() != 1);
}
private void switchStreamSource(Model selectedModel) {
var couldntSwitchHeaderText = "Couldn't switch stream resolution";
try {
if (!selectedModel.isOnline(true)) {
Dialogs.showError(source.getScene(), couldntSwitchHeaderText, "The resolution can only be changed, when the model is online", null);
return;
}
} catch (InterruptedException e1) {
Thread.currentThread().interrupt();
Dialogs.showError(source.getScene(), couldntSwitchHeaderText, "An error occured while checking, if the model is online", null);
return;
} catch (IOException | ExecutionException e1) {
Dialogs.showError(source.getScene(), couldntSwitchHeaderText, "An error occured while checking, if the model is online", null);
return;
}
Consumer<Model> onSuccess = m -> {
try {
recorder.switchStreamSource(m);
} catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException | IOException e) {
LOG.error(couldntSwitchHeaderText, 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) {
showErrorDialog(throwable, "Couldn't switch stream resolution", "Error while switching stream resolution");
}
private void showErrorDialog(Throwable throwable, String header, String msg) {
Alert alert = new AutosizeAlert(Alert.AlertType.ERROR, source.getScene());
alert.setTitle("Error");
alert.setHeaderText(header);
alert.setContentText(msg + ": " + throwable.getLocalizedMessage());
alert.showAndWait();
}
private void addGroupMenu(ContextMenu menu, List<Model> selectedModels) {
var model = selectedModels.get(0);
var addToGroup = new MenuItem("Add to group");
addToGroup.setOnAction(e -> new AddToGroupAction(source, recorder, model).execute());
var groupSubMenu = new ModelGroupMenuBuilder().model(model).recorder(recorder).node(source).build();
addToGroup.setOnAction(e -> new AddToGroupAction(source, recorder, selectedModels).execute(callback));
var groupSubMenu = new ModelGroupMenuBuilder() // @formatter:off
.model(model)
.recorder(recorder)
.node(source)
.callback(m -> callback.run())
.build(); // @formatter:on
Optional<ModelGroup> modelGroup = recorder.getModelGroup(model);
menu.getItems().add(modelGroup.isEmpty() ? addToGroup : groupSubMenu);
}
@ -279,15 +379,33 @@ public class ModelMenuContributor {
}
private void addStartRecordingWithTimeLimit(ContextMenu menu, List<Model> selectedModels) {
var text = recorder.isTracked(selectedModels.get(0)) ? "Record Until" : "Start Recording Until";
var model = selectedModels.get(0);
var text = recorder.isTracked(model) ? "Record Until" : "Start Recording Until";
var start = new MenuItem(text);
menu.getItems().add(start);
start.setOnAction(e -> {
startStopAction(selectedModels, true);
selectedModels.forEach(m -> new SetStopDateAction(source, m, recorder).execute());
selectedModels.forEach(m -> new SetStopDateAction(source, m, recorder).execute() //
.thenAccept(b -> executeCallback()));
});
}
private void addRemoveTimeLimit(ContextMenu menu, List<Model> selectedModels) {
var model = selectedModels.get(0);
if (!model.isRecordingTimeLimited()) {
return;
}
var removeTimeLimit = new MenuItem("Remove Time Limit");
removeTimeLimit.setOnAction(e -> removeTimeLimit(model));
menu.getItems().add(removeTimeLimit);
}
private void removeTimeLimit(Model selectedModel) {
new RemoveTimeLimitAction(source, selectedModel, recorder) //
.execute() //
.whenComplete((result, exception) -> executeCallback());
}
private void addOpenInPlayer(ContextMenu menu, List<Model> selectedModels) {
var openInPlayer = new MenuItem("Open in Player");
openInPlayer.setOnAction(e -> selectedModels.forEach(m -> new PlayAction(source, m).execute()));
@ -343,4 +461,12 @@ public class ModelMenuContributor {
private void stopRecording(List<Model> models) {
new StopRecordingAction(source, models, recorder).execute(startStopCallback);
}
private void executeCallback() {
try {
callback.run();
} catch (Exception e) {
LOG.error("Error while executing menu callback", e);
}
}
}

View File

@ -26,7 +26,6 @@ import ctbrec.ui.DesktopIntegration;
import ctbrec.ui.JavaFxModel;
import ctbrec.ui.PreviewPopupHandler;
import ctbrec.ui.action.CheckModelAccountAction;
import ctbrec.ui.action.EditNotesAction;
import ctbrec.ui.action.FollowAction;
import ctbrec.ui.action.IgnoreModelsAction;
import ctbrec.ui.action.PlayAction;
@ -501,16 +500,13 @@ public class RecordLaterTab extends Tab implements TabSelectionListener {
follow.setDisable(!selectedModels.stream().allMatch(m -> m.getSite().supportsFollow() && m.getSite().credentialsAvailable()));
var ignore = new MenuItem("Ignore");
ignore.setOnAction(e -> ignore(selectedModels));
var notes = new MenuItem("Notes");
notes.setOnAction(e -> notes(selectedModels));
ContextMenu menu = new CustomMouseBehaviorContextMenu(start, stop, copyUrl, openInPlayer, openInBrowser, follow, notes, ignore);
ContextMenu menu = new CustomMouseBehaviorContextMenu(start, stop, copyUrl, openInPlayer, openInBrowser, follow, ignore);
if (selectedModels.size() > 1) {
copyUrl.setDisable(true);
openInPlayer.setDisable(true);
openInBrowser.setDisable(true);
notes.setDisable(true);
}
return menu;
@ -524,10 +520,6 @@ public class RecordLaterTab extends Tab implements TabSelectionListener {
new FollowAction(getTabPane(), new ArrayList<>(selectedModels)).execute();
}
private void notes(ObservableList<JavaFxModel> selectedModels) {
new EditNotesAction(getTabPane(), selectedModels.get(0), table).execute();
}
private void openInPlayer(JavaFxModel selectedModel) {
new PlayAction(getTabPane(), selectedModel).execute();
}

View File

@ -6,18 +6,15 @@ import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@ -34,20 +31,10 @@ import ctbrec.sites.Site;
import ctbrec.ui.AutosizeAlert;
import ctbrec.ui.JavaFxModel;
import ctbrec.ui.PreviewPopupHandler;
import ctbrec.ui.StreamSourceSelectionDialog;
import ctbrec.ui.action.AddToGroupAction;
import ctbrec.ui.action.CheckModelAccountAction;
import ctbrec.ui.action.EditNotesAction;
import ctbrec.ui.action.FollowAction;
import ctbrec.ui.action.IgnoreModelsAction;
import ctbrec.ui.action.OpenRecordingsDir;
import ctbrec.ui.action.OpenUrlAction;
import ctbrec.ui.action.PauseAction;
import ctbrec.ui.action.PlayAction;
import ctbrec.ui.action.RemoveTimeLimitAction;
import ctbrec.ui.action.ResumeAction;
import ctbrec.ui.action.SetStopDateAction;
import ctbrec.ui.action.StartRecordingAction;
import ctbrec.ui.action.StopRecordingAction;
import ctbrec.ui.action.ToggleRecordingAction;
import ctbrec.ui.controls.CustomMouseBehaviorContextMenu;
@ -56,7 +43,7 @@ import ctbrec.ui.controls.Dialogs;
import ctbrec.ui.controls.SearchBox;
import ctbrec.ui.controls.autocomplete.AutoFillTextField;
import ctbrec.ui.controls.autocomplete.ObservableListSuggester;
import ctbrec.ui.menu.ModelGroupMenuBuilder;
import ctbrec.ui.menu.ModelMenuContributor;
import ctbrec.ui.tabs.TabSelectionListener;
import javafx.application.Platform;
import javafx.beans.property.SimpleObjectProperty;
@ -71,12 +58,11 @@ import javafx.concurrent.WorkerStateEvent;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.Tab;
@ -92,8 +78,6 @@ import javafx.scene.control.Tooltip;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.ContextMenuEvent;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
@ -505,6 +489,7 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
filteredModels.clear();
filter(filter.getText());
table.sort();
table.refresh();
}
private void addOrUpdateModels(List<JavaFxModel> updatedModels) {
@ -635,162 +620,21 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
}
private ContextMenu createContextMenu() {
ObservableList<JavaFxModel> selectedModels = table.getSelectionModel().getSelectedItems();
List<Model> selectedModels = table.getSelectionModel().getSelectedItems().stream().map(JavaFxModel::getDelegate).collect(Collectors.toList());
if (selectedModels.isEmpty()) {
return null;
}
var stop = new MenuItem("Remove Model");
stop.setOnAction(e -> stopAction(selectedModels));
var recordLater = new MenuItem("Record Later");
recordLater.setOnAction(e -> recordLater(selectedModels));
var copyUrl = new MenuItem("Copy URL");
copyUrl.setOnAction(e -> {
Model selected = selectedModels.get(0);
final var clipboard = Clipboard.getSystemClipboard();
final var content = new ClipboardContent();
content.putString(selected.getUrl());
clipboard.setContent(content);
});
ContextMenu menu = new CustomMouseBehaviorContextMenu();
var pauseRecording = new MenuItem("Pause Recording");
pauseRecording.setOnAction(e -> pauseRecording(selectedModels));
var resumeRecording = new MenuItem("Resume Recording");
resumeRecording.setOnAction(e -> resumeRecording(selectedModels));
var stopRecordingAt = new MenuItem("Stop Recording at Date");
stopRecordingAt.setOnAction(e -> setStopDate(selectedModels.get(0)));
var removeTimeLimit = new MenuItem("Remove Time Limit");
removeTimeLimit.setOnAction(e -> removeTimeLimit(selectedModels.get(0)));
var openInBrowser = new MenuItem("Open in Browser");
openInBrowser.setOnAction(e -> openInBrowser(selectedModels));
var openInPlayer = new MenuItem("Open in Player");
openInPlayer.setOnAction(e -> openInPlayer(selectedModels.get(0)));
var switchStreamSource = new MenuItem("Switch resolution");
switchStreamSource.setOnAction(e -> switchStreamSource(selectedModels.get(0)));
var follow = new MenuItem("Follow");
follow.setOnAction(e -> follow(selectedModels));
follow.setDisable(!selectedModels.stream().allMatch(m -> m.getSite().supportsFollow() && m.getSite().credentialsAvailable()));
var ignore = new MenuItem("Ignore");
ignore.setOnAction(e -> ignore(selectedModels));
var notes = new MenuItem("Notes");
notes.setOnAction(e -> notes(selectedModels));
var openRecDir = new MenuItem("Open recording directory");
openRecDir.setOnAction(e -> new OpenRecordingsDir(table, selectedModels.get(0)).execute());
var addToGroup = new MenuItem("Add to group");
addToGroup.setOnAction(e -> new AddToGroupAction(this.getContent(), recorder, selectedModels.get(0)).execute(() -> table.refresh()));
var groupSubMenu = createModelGroupMenu(selectedModels);
ContextMenu menu = new CustomMouseBehaviorContextMenu(stop, recordLater);
if (selectedModels.size() == 1) {
menu.getItems().add(selectedModels.get(0).isSuspended() ? resumeRecording : pauseRecording);
menu.getItems().add(stopRecordingAt);
if (selectedModels.get(0).isRecordingTimeLimited()) {
menu.getItems().add(removeTimeLimit);
}
} else {
menu.getItems().addAll(resumeRecording, pauseRecording);
}
Optional<ModelGroup> modelGroup = recorder.getModelGroup(selectedModels.get(0));
menu.getItems().add(modelGroup.isEmpty() ? addToGroup : groupSubMenu);
menu.getItems().addAll(copyUrl, openInPlayer, openInBrowser, openRecDir, switchStreamSource, follow, notes, ignore);
if (selectedModels.size() > 1) {
copyUrl.setDisable(true);
openInPlayer.setDisable(true);
switchStreamSource.setDisable(true);
notes.setDisable(true);
}
ModelMenuContributor.newContributor(getTabPane(), Config.getInstance(), recorder) //
.withStartStopCallback(m -> getTabPane().setCursor(Cursor.DEFAULT)) //
.afterwards(table::refresh)
.contributeToMenu(selectedModels, menu);
return menu;
}
private void openInBrowser(ObservableList<JavaFxModel> selectedModels) {
List<Model> models = selectedModels.stream().map(JavaFxModel::getDelegate).collect(Collectors.toList());
new OpenUrlAction(getTabPane(), models).execute();
}
private Menu createModelGroupMenu(ObservableList<JavaFxModel> selectedModels) {
return new ModelGroupMenuBuilder() //
.model(selectedModels.get(0)) //
.recorder(recorder) //
.node(table) //
.callback(m -> table.refresh()) //
.build();
}
private void setStopDate(JavaFxModel model) {
new SetStopDateAction(table, model.getDelegate(), recorder) //
.execute() //
.whenComplete((result, exception) -> table.refresh());
}
private void removeTimeLimit(JavaFxModel selectedModel) {
new RemoveTimeLimitAction(table, selectedModel.getDelegate(), recorder) //
.execute() //
.whenComplete((result, exception) -> table.refresh());
}
private void ignore(ObservableList<JavaFxModel> selectedModels) {
new IgnoreModelsAction(table, selectedModels, recorder, true).execute();
}
private void follow(ObservableList<JavaFxModel> selectedModels) {
new FollowAction(getTabPane(), new ArrayList<>(selectedModels)).execute();
}
private void notes(ObservableList<JavaFxModel> selectedModels) {
new EditNotesAction(getTabPane(), selectedModels.get(0), table).execute();
}
private void openInPlayer(JavaFxModel selectedModel) {
new PlayAction(getTabPane(), selectedModel).execute();
}
private void switchStreamSource(JavaFxModel fxModel) {
var couldntSwitchHeaderText = "Couldn't switch stream resolution";
try {
if (!fxModel.isOnline(true)) {
Dialogs.showError(getTabPane().getScene(), couldntSwitchHeaderText, "The resolution can only be changed, when the model is online", null);
return;
}
} catch (InterruptedException e1) {
Thread.currentThread().interrupt();
Dialogs.showError(getTabPane().getScene(), couldntSwitchHeaderText, "An error occured while checking, if the model is online", null);
return;
} catch (IOException | ExecutionException e1) {
Dialogs.showError(getTabPane().getScene(), couldntSwitchHeaderText, "An error occured while checking, if the model is online", null);
return;
}
Consumer<Model> onSuccess = m -> {
try {
recorder.switchStreamSource(m);
} catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException | IOException e) {
LOG.error(couldntSwitchHeaderText, e);
showStreamSwitchErrorDialog(e);
}
};
Consumer<Throwable> onFail = t -> {
LOG.error(couldntSwitchHeaderText, t);
showStreamSwitchErrorDialog(t);
};
StreamSourceSelectionDialog.show(getTabPane().getScene(), fxModel.getDelegate(), onSuccess, onFail);
}
private void showStreamSwitchErrorDialog(Throwable throwable) {
showErrorDialog(throwable, "Couldn't switch stream resolution", "Error while switching stream resolution");
}
private void showErrorDialog(Throwable throwable, String header, String msg) {
Alert alert = new AutosizeAlert(Alert.AlertType.ERROR, getTabPane().getScene());
alert.setTitle("Error");
alert.setHeaderText(header);
alert.setContentText(msg + ": " + throwable.getLocalizedMessage());
alert.showAndWait();
}
private boolean stopAction(List<JavaFxModel> selectedModels) {
var confirmed = true;
if (Config.getInstance().getSettings().confirmationForDangerousActions) {
@ -809,17 +653,6 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
return confirmed;
}
private void recordLater(List<JavaFxModel> selectedModels) {
boolean confirmed = stopAction(selectedModels);
if (confirmed) {
List<Model> models = selectedModels.stream().map(JavaFxModel::getDelegate).map(m -> {
m.setMarkedForLaterRecording(true);
return m;
}).collect(Collectors.toList());
new StartRecordingAction(table, models, recorder).execute();
}
}
private void pauseRecording(List<JavaFxModel> selectedModels) {
List<Model> models = selectedModels.stream().map(JavaFxModel::getDelegate).collect(Collectors.toList());
new PauseAction(getTabPane(), models, recorder).execute();