forked from j62/ctbrec
Fix bug in moveActiveRecordingsToFront
There was a bug in moveActiveRecordingsToFront, which caused the models to rotate their positions Also some refactoring to reduce method complexity.
This commit is contained in:
parent
2b426afe2e
commit
87943fac95
|
@ -7,7 +7,6 @@ import java.net.SocketTimeoutException;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -85,7 +84,7 @@ import javafx.scene.transform.Transform;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
|
|
||||||
public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
private static final transient Logger LOG = LoggerFactory.getLogger(ThumbOverviewTab.class);
|
private static final Logger LOG = LoggerFactory.getLogger(ThumbOverviewTab.class);
|
||||||
|
|
||||||
protected static BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
|
protected static BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
|
||||||
static ExecutorService threadPool = new ThreadPoolExecutor(2, 2, 10, TimeUnit.MINUTES, queue, createThreadFactory());
|
static ExecutorService threadPool = new ThreadPoolExecutor(2, 2, 10, TimeUnit.MINUTES, queue, createThreadFactory());
|
||||||
|
@ -173,7 +172,7 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
topBar.getChildren().add(filterInput);
|
topBar.getChildren().add(filterInput);
|
||||||
if (site.supportsTips() && site.credentialsAvailable()) {
|
if (site.supportsTips() && site.credentialsAvailable()) {
|
||||||
Button buyTokens = new Button("Buy Tokens");
|
Button buyTokens = new Button("Buy Tokens");
|
||||||
buyTokens.setOnAction((e) -> DesktopIntegration.open(site.getBuyTokensLink()));
|
buyTokens.setOnAction(e -> DesktopIntegration.open(site.getBuyTokensLink()));
|
||||||
TokenLabel tokenBalance = new TokenLabel(site);
|
TokenLabel tokenBalance = new TokenLabel(site);
|
||||||
tokenBalance.setAlignment(Pos.CENTER_RIGHT);
|
tokenBalance.setAlignment(Pos.CENTER_RIGHT);
|
||||||
tokenBalance.prefHeightProperty().bind(buyTokens.heightProperty());
|
tokenBalance.prefHeightProperty().bind(buyTokens.heightProperty());
|
||||||
|
@ -196,15 +195,15 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
pagination.getChildren().add(pageInput);
|
pagination.getChildren().add(pageInput);
|
||||||
BorderPane.setMargin(pagination, new Insets(5));
|
BorderPane.setMargin(pagination, new Insets(5));
|
||||||
pageInput.setPrefWidth(50);
|
pageInput.setPrefWidth(50);
|
||||||
pageInput.setOnAction((e) -> handlePageNumberInput());
|
pageInput.setOnAction(e -> handlePageNumberInput());
|
||||||
pagePrev.setOnAction((e) -> {
|
pagePrev.setOnAction(e -> {
|
||||||
int page = updateService.getPage();
|
int page = updateService.getPage();
|
||||||
page = Math.max(1, --page);
|
page = Math.max(1, --page);
|
||||||
pageInput.setText(Integer.toString(page));
|
pageInput.setText(Integer.toString(page));
|
||||||
updateService.setPage(page);
|
updateService.setPage(page);
|
||||||
restartUpdateService();
|
restartUpdateService();
|
||||||
});
|
});
|
||||||
pageNext.setOnAction((e) -> {
|
pageNext.setOnAction(e -> {
|
||||||
int page = updateService.getPage();
|
int page = updateService.getPage();
|
||||||
page++;
|
page++;
|
||||||
pageInput.setText(Integer.toString(page));
|
pageInput.setText(Integer.toString(page));
|
||||||
|
@ -224,7 +223,7 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
thumbWidths.add(360);
|
thumbWidths.add(360);
|
||||||
thumbWidth = new ComboBox<>(FXCollections.observableList(thumbWidths));
|
thumbWidth = new ComboBox<>(FXCollections.observableList(thumbWidths));
|
||||||
thumbWidth.getSelectionModel().select(Integer.valueOf(Config.getInstance().getSettings().thumbWidth));
|
thumbWidth.getSelectionModel().select(Integer.valueOf(Config.getInstance().getSettings().thumbWidth));
|
||||||
thumbWidth.setOnAction((e) -> {
|
thumbWidth.setOnAction(e -> {
|
||||||
int width = thumbWidth.getSelectionModel().getSelectedItem();
|
int width = thumbWidth.getSelectionModel().getSelectedItem();
|
||||||
Config.getInstance().getSettings().thumbWidth = width;
|
Config.getInstance().getSettings().thumbWidth = width;
|
||||||
updateThumbSize();
|
updateThumbSize();
|
||||||
|
@ -253,51 +252,10 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
if(searchTask != null) {
|
if(searchTask != null) {
|
||||||
searchTask.cancel(true);
|
searchTask.cancel(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(newValue.length() < 2) {
|
if(newValue.length() < 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
searchTask = new ThumbOverviewTabSearchTask(site, popover, popoverTreelist, newValue);
|
||||||
|
|
||||||
searchTask = new Task<List<Model>>() {
|
|
||||||
@Override
|
|
||||||
protected List<Model> call() throws Exception {
|
|
||||||
if(site.searchRequiresLogin()) {
|
|
||||||
boolean loggedin = false;
|
|
||||||
try {
|
|
||||||
loggedin = SiteUiFactory.getUi(site).login();
|
|
||||||
} catch (IOException e) {
|
|
||||||
loggedin = false;
|
|
||||||
}
|
|
||||||
if(!loggedin) {
|
|
||||||
showError("Login failed", "Search won't work correctly without login", null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return site.search(newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void failed() {
|
|
||||||
LOG.error("Search failed", getException());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void succeeded() {
|
|
||||||
Platform.runLater(() -> {
|
|
||||||
List<Model> models = getValue();
|
|
||||||
LOG.debug("Search result {} {}", isCancelled(), models);
|
|
||||||
if(models.isEmpty()) {
|
|
||||||
popover.hide();
|
|
||||||
} else {
|
|
||||||
popoverTreelist.getItems().clear();
|
|
||||||
for (Model model : getValue()) {
|
|
||||||
popoverTreelist.getItems().add(model);
|
|
||||||
}
|
|
||||||
popover.show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
new Thread(searchTask).start();
|
new Thread(searchTask).start();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -323,6 +281,7 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
updateService.setPage(page);
|
updateService.setPage(page);
|
||||||
restartUpdateService();
|
restartUpdateService();
|
||||||
} catch(NumberFormatException e) {
|
} catch(NumberFormatException e) {
|
||||||
|
// noop
|
||||||
} finally {
|
} finally {
|
||||||
pageInput.setText(Integer.toString(updateService.getPage()));
|
pageInput.setText(Integer.toString(updateService.getPage()));
|
||||||
}
|
}
|
||||||
|
@ -343,8 +302,8 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
void initializeUpdateService() {
|
void initializeUpdateService() {
|
||||||
int refreshRate = Config.getInstance().getSettings().overviewUpdateIntervalInSecs;
|
int refreshRate = Config.getInstance().getSettings().overviewUpdateIntervalInSecs;
|
||||||
updateService.setPeriod(new Duration(TimeUnit.SECONDS.toMillis(refreshRate)));
|
updateService.setPeriod(new Duration(TimeUnit.SECONDS.toMillis(refreshRate)));
|
||||||
updateService.setOnSucceeded((event) -> onSuccess());
|
updateService.setOnSucceeded(event -> onSuccess());
|
||||||
updateService.setOnFailed((event) -> onFail(event));
|
updateService.setOnFailed(this::onFail);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onSuccess() {
|
protected void onSuccess() {
|
||||||
|
@ -368,21 +327,28 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
ObservableList<Node> nodes = grid.getChildren();
|
ObservableList<Node> nodes = grid.getChildren();
|
||||||
|
|
||||||
// first remove models, which are not in the updated list
|
// first remove models, which are not in the updated list
|
||||||
for (Iterator<Node> iterator = nodes.iterator(); iterator.hasNext();) {
|
removeModelsMissingInUpdate(nodes, models);
|
||||||
Node node = iterator.next();
|
|
||||||
if (!(node instanceof ThumbCell)) continue;
|
// now update existing cells and create new ones models, which are new in the update
|
||||||
ThumbCell cell = (ThumbCell) node;
|
createOrUpdateModelCells(nodes, models);
|
||||||
if(!models.contains(cell.getModel())) {
|
|
||||||
iterator.remove();
|
// reapply the filter
|
||||||
|
filteredThumbCells.clear();
|
||||||
|
filter();
|
||||||
|
|
||||||
|
// move models, which are tracked by the recorder to the front
|
||||||
|
moveActiveRecordingsToFront();
|
||||||
|
} finally {
|
||||||
|
gridLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createOrUpdateModelCells(ObservableList<Node> nodes, List<? extends Model> models) {
|
||||||
List<ThumbCell> positionChangedOrNew = new ArrayList<>();
|
List<ThumbCell> positionChangedOrNew = new ArrayList<>();
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (Model model : models) {
|
for (Model model : models) {
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (Iterator<Node> iterator = nodes.iterator(); iterator.hasNext();) {
|
for (Node node : nodes) { // NOSONAR
|
||||||
Node node = iterator.next();
|
|
||||||
if (!(node instanceof ThumbCell)) continue;
|
if (!(node instanceof ThumbCell)) continue;
|
||||||
ThumbCell cell = (ThumbCell) node;
|
ThumbCell cell = (ThumbCell) node;
|
||||||
if(cell.getModel().equals(model)) {
|
if(cell.getModel().equals(model)) {
|
||||||
|
@ -392,15 +358,20 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
cell.setIndex(index);
|
cell.setIndex(index);
|
||||||
positionChangedOrNew.add(cell);
|
positionChangedOrNew.add(cell);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!found) {
|
if(!found) {
|
||||||
ThumbCell newCell = createThumbCell(this, model, recorder);
|
ThumbCell newCell = createThumbCell(model, recorder);
|
||||||
newCell.setIndex(index);
|
newCell.setIndex(index);
|
||||||
positionChangedOrNew.add(newCell);
|
positionChangedOrNew.add(newCell);
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
rearrangeCells(nodes, positionChangedOrNew);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rearrangeCells(ObservableList<Node> nodes, List<ThumbCell> positionChangedOrNew) {
|
||||||
for (ThumbCell thumbCell : positionChangedOrNew) {
|
for (ThumbCell thumbCell : positionChangedOrNew) {
|
||||||
nodes.remove(thumbCell);
|
nodes.remove(thumbCell);
|
||||||
if(thumbCell.getIndex() < nodes.size()) {
|
if(thumbCell.getIndex() < nodes.size()) {
|
||||||
|
@ -409,22 +380,26 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
nodes.add(thumbCell);
|
nodes.add(thumbCell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
filteredThumbCells.clear();
|
private void removeModelsMissingInUpdate(ObservableList<Node> nodes, List<? extends Model> models) {
|
||||||
filter();
|
for (Iterator<Node> iterator = nodes.iterator(); iterator.hasNext();) {
|
||||||
moveActiveRecordingsToFront();
|
Node node = iterator.next();
|
||||||
} finally {
|
if (!(node instanceof ThumbCell)) continue;
|
||||||
gridLock.unlock();
|
ThumbCell cell = (ThumbCell) node;
|
||||||
|
if (!models.contains(cell.getModel())) {
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThumbCell createThumbCell(ThumbOverviewTab thumbOverviewTab, Model model, Recorder recorder) {
|
ThumbCell createThumbCell(Model model, Recorder recorder) {
|
||||||
ThumbCell newCell = new ThumbCell(this, model, recorder);
|
ThumbCell newCell = new ThumbCell(this, model, recorder);
|
||||||
newCell.addEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, event -> {
|
newCell.addEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, event -> {
|
||||||
suspendUpdates(true);
|
suspendUpdates(true);
|
||||||
popup = createContextMenu(newCell);
|
popup = createContextMenu(newCell);
|
||||||
popup.show(newCell, event.getScreenX(), event.getScreenY());
|
popup.show(newCell, event.getScreenX(), event.getScreenY());
|
||||||
popup.setOnHidden((e) -> suspendUpdates(false));
|
popup.setOnHidden(e -> suspendUpdates(false));
|
||||||
event.consume();
|
event.consume();
|
||||||
});
|
});
|
||||||
newCell.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> {
|
newCell.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> {
|
||||||
|
@ -435,7 +410,7 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
newCell.selectionProperty().addListener((obs, oldValue, newValue) -> {
|
newCell.selectionProperty().addListener((obs, oldValue, newValue) -> {
|
||||||
if(newValue) {
|
if(newValue.booleanValue()) {
|
||||||
selectedThumbCells.add(newCell);
|
selectedThumbCells.add(newCell);
|
||||||
} else {
|
} else {
|
||||||
selectedThumbCells.remove(newCell);
|
selectedThumbCells.remove(newCell);
|
||||||
|
@ -447,75 +422,32 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
|
|
||||||
private ContextMenu createContextMenu(ThumbCell cell) {
|
private ContextMenu createContextMenu(ThumbCell cell) {
|
||||||
MenuItem openInPlayer = new MenuItem("Open in Player");
|
MenuItem openInPlayer = new MenuItem("Open in Player");
|
||||||
openInPlayer.setOnAction((e) -> startPlayer(getSelectedThumbCells(cell)));
|
openInPlayer.setOnAction(e -> startPlayer(getSelectedThumbCells(cell)));
|
||||||
|
|
||||||
MenuItem start = new MenuItem("Start Recording");
|
MenuItem start = new MenuItem("Start Recording");
|
||||||
start.setOnAction((e) -> startStopAction(getSelectedThumbCells(cell), true));
|
start.setOnAction(e -> startStopAction(getSelectedThumbCells(cell), true));
|
||||||
MenuItem stop = new MenuItem("Stop Recording");
|
MenuItem stop = new MenuItem("Stop Recording");
|
||||||
stop.setOnAction((e) -> startStopAction(getSelectedThumbCells(cell), false));
|
stop.setOnAction(e -> startStopAction(getSelectedThumbCells(cell), false));
|
||||||
MenuItem startStop = recorder.isTracked(cell.getModel()) ? stop : start;
|
MenuItem startStop = recorder.isTracked(cell.getModel()) ? stop : start;
|
||||||
|
|
||||||
MenuItem pause = new MenuItem("Pause Recording");
|
MenuItem pause = new MenuItem("Pause Recording");
|
||||||
pause.setOnAction((e) -> pauseResumeAction(getSelectedThumbCells(cell), true));
|
pause.setOnAction(e -> pauseResumeAction(getSelectedThumbCells(cell), true));
|
||||||
MenuItem resume = new MenuItem("Resume Recording");
|
MenuItem resume = new MenuItem("Resume Recording");
|
||||||
resume.setOnAction((e) -> pauseResumeAction(getSelectedThumbCells(cell), false));
|
resume.setOnAction(e -> pauseResumeAction(getSelectedThumbCells(cell), false));
|
||||||
MenuItem pauseResume = recorder.isSuspended(cell.getModel()) ? resume : pause;
|
MenuItem pauseResume = recorder.isSuspended(cell.getModel()) ? resume : pause;
|
||||||
|
|
||||||
MenuItem follow = new MenuItem("Follow");
|
MenuItem follow = new MenuItem("Follow");
|
||||||
follow.setOnAction((e) -> follow(getSelectedThumbCells(cell), true));
|
follow.setOnAction(e -> follow(getSelectedThumbCells(cell), true));
|
||||||
MenuItem unfollow = new MenuItem("Unfollow");
|
MenuItem unfollow = new MenuItem("Unfollow");
|
||||||
unfollow.setOnAction((e) -> follow(getSelectedThumbCells(cell), false));
|
unfollow.setOnAction(e -> follow(getSelectedThumbCells(cell), false));
|
||||||
|
|
||||||
MenuItem copyUrl = new MenuItem("Copy URL");
|
|
||||||
copyUrl.setOnAction((e) -> {
|
|
||||||
final Clipboard clipboard = Clipboard.getSystemClipboard();
|
|
||||||
final ClipboardContent content = new ClipboardContent();
|
|
||||||
content.putString(cell.getModel().getUrl());
|
|
||||||
clipboard.setContent(content);
|
|
||||||
});
|
|
||||||
|
|
||||||
MenuItem ignore = new MenuItem("Ignore");
|
MenuItem ignore = new MenuItem("Ignore");
|
||||||
ignore.setOnAction((e) -> ignore(getSelectedThumbCells(cell)));
|
ignore.setOnAction(e -> ignore(getSelectedThumbCells(cell)));
|
||||||
|
|
||||||
MenuItem sendTip = new MenuItem("Send Tip");
|
MenuItem copyUrl = createCopyUrlMenuItem(cell);
|
||||||
sendTip.setOnAction((e) -> {
|
MenuItem sendTip = createTipMenuItem(cell);
|
||||||
TipDialog tipDialog = new TipDialog(getTabPane().getScene(), site, cell.getModel());
|
|
||||||
tipDialog.showAndWait();
|
|
||||||
String tipText = tipDialog.getResult();
|
|
||||||
if(tipText != null) {
|
|
||||||
DecimalFormat df = new DecimalFormat("0.##");
|
|
||||||
try {
|
|
||||||
Number tokens = df.parse(tipText);
|
|
||||||
SiteUiFactory.getUi(site).login();
|
|
||||||
cell.getModel().receiveTip(tokens.doubleValue());
|
|
||||||
Map<String, Object> event = new HashMap<>();
|
|
||||||
event.put("event", "tokens.sent");
|
|
||||||
event.put("amount", tokens.doubleValue());
|
|
||||||
EventBusHolder.BUS.post(event);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
LOG.error("An error occured while sending tip", ex);
|
|
||||||
showError("Couldn't send tip", "An error occured while sending tip:", ex);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
showError("Couldn't send tip", "You entered an invalid amount of tokens", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
sendTip.setDisable(!site.credentialsAvailable());
|
|
||||||
|
|
||||||
// check, if other cells are selected, too. in that case, we have to disable menu item, which make sense only for
|
configureItemsForSelection(cell, openInPlayer, copyUrl, sendTip);
|
||||||
// single selections. but only do that, if the popup has been triggered on a selected cell. otherwise remove the
|
|
||||||
// selection and show the normal menu
|
|
||||||
if (selectedThumbCells.size() > 1 || selectedThumbCells.size() == 1 && selectedThumbCells.get(0) != cell) {
|
|
||||||
if(cell.isSelected()) {
|
|
||||||
if(Config.getInstance().getSettings().singlePlayer) {
|
|
||||||
openInPlayer.setDisable(true);
|
|
||||||
}
|
|
||||||
copyUrl.setDisable(true);
|
|
||||||
sendTip.setDisable(true);
|
|
||||||
} else {
|
|
||||||
removeSelection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ContextMenu contextMenu = new ContextMenu();
|
ContextMenu contextMenu = new ContextMenu();
|
||||||
contextMenu.setAutoHide(true);
|
contextMenu.setAutoHide(true);
|
||||||
|
@ -542,6 +474,63 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
return contextMenu;
|
return contextMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check, if other cells are selected, too. in that case, we have to disable menu items, which make sense only for
|
||||||
|
* single selections. but only do that, if the popup has been triggered on a selected cell. otherwise remove the
|
||||||
|
* selection and show the normal menu
|
||||||
|
*/
|
||||||
|
private void configureItemsForSelection(ThumbCell cell, MenuItem openInPlayer, MenuItem copyUrl, MenuItem sendTip) {
|
||||||
|
if (selectedThumbCells.size() > 1 || selectedThumbCells.size() == 1 && selectedThumbCells.get(0) != cell) {
|
||||||
|
if(cell.isSelected()) {
|
||||||
|
if(Config.getInstance().getSettings().singlePlayer) {
|
||||||
|
openInPlayer.setDisable(true);
|
||||||
|
}
|
||||||
|
copyUrl.setDisable(true);
|
||||||
|
sendTip.setDisable(true);
|
||||||
|
} else {
|
||||||
|
removeSelection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private MenuItem createCopyUrlMenuItem(ThumbCell cell) {
|
||||||
|
MenuItem copyUrl = new MenuItem("Copy URL");
|
||||||
|
copyUrl.setOnAction(e -> {
|
||||||
|
final Clipboard clipboard = Clipboard.getSystemClipboard();
|
||||||
|
final ClipboardContent content = new ClipboardContent();
|
||||||
|
content.putString(cell.getModel().getUrl());
|
||||||
|
clipboard.setContent(content);
|
||||||
|
});
|
||||||
|
return copyUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MenuItem createTipMenuItem(ThumbCell cell) {
|
||||||
|
MenuItem sendTip = new MenuItem("Send Tip");
|
||||||
|
sendTip.setOnAction(e -> {
|
||||||
|
TipDialog tipDialog = new TipDialog(getTabPane().getScene(), site, cell.getModel());
|
||||||
|
tipDialog.showAndWait();
|
||||||
|
String tipText = tipDialog.getResult();
|
||||||
|
if(tipText != null) {
|
||||||
|
DecimalFormat df = new DecimalFormat("0.##");
|
||||||
|
try {
|
||||||
|
Number tokens = df.parse(tipText);
|
||||||
|
SiteUiFactory.getUi(site).login();
|
||||||
|
cell.getModel().receiveTip(tokens.doubleValue());
|
||||||
|
Map<String, Object> event = new HashMap<>();
|
||||||
|
event.put("event", "tokens.sent");
|
||||||
|
event.put("amount", tokens.doubleValue());
|
||||||
|
EventBusHolder.BUS.post(event);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOG.error("An error occured while sending tip", ex);
|
||||||
|
showError("Couldn't send tip", "An error occured while sending tip:", ex);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
showError("Couldn't send tip", "You entered an invalid amount of tokens", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sendTip.setDisable(!site.credentialsAvailable());
|
||||||
|
return sendTip;
|
||||||
|
}
|
||||||
|
|
||||||
private List<ThumbCell> getSelectedThumbCells(ThumbCell cell) {
|
private List<ThumbCell> getSelectedThumbCells(ThumbCell cell) {
|
||||||
if(selectedThumbCells.isEmpty()) {
|
if(selectedThumbCells.isEmpty()) {
|
||||||
return Collections.singletonList(cell);
|
return Collections.singletonList(cell);
|
||||||
|
@ -552,8 +541,8 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
|
|
||||||
protected void follow(List<ThumbCell> selection, boolean follow) {
|
protected void follow(List<ThumbCell> selection, boolean follow) {
|
||||||
for (ThumbCell thumbCell : selection) {
|
for (ThumbCell thumbCell : selection) {
|
||||||
thumbCell.follow(follow).thenAccept((success) -> {
|
thumbCell.follow(follow).thenAccept(success -> {
|
||||||
if(follow && success) {
|
if(follow && success.booleanValue()) {
|
||||||
showAddToFollowedAnimation(thumbCell);
|
showAddToFollowedAnimation(thumbCell);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -600,9 +589,7 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
scale.setToY(0.1);
|
scale.setToY(0.1);
|
||||||
ParallelTransition pt = new ParallelTransition(translate, scale);
|
ParallelTransition pt = new ParallelTransition(translate, scale);
|
||||||
pt.play();
|
pt.play();
|
||||||
pt.setOnFinished((evt) -> {
|
pt.setOnFinished(evt -> root.getChildren().remove(iv));
|
||||||
root.getChildren().remove(iv);
|
|
||||||
});
|
|
||||||
|
|
||||||
String normalStyle = followedTab.getStyle();
|
String normalStyle = followedTab.getStyle();
|
||||||
Color normal = Color.web("#f4f4f4");
|
Color normal = Color.web("#f4f4f4");
|
||||||
|
@ -631,7 +618,7 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
};
|
};
|
||||||
blink.setCycleCount(6);
|
blink.setCycleCount(6);
|
||||||
blink.setAutoReverse(true);
|
blink.setAutoReverse(true);
|
||||||
blink.setOnFinished((evt) -> followedTab.setStyle(normalStyle));
|
blink.setOnFinished(evt -> followedTab.setStyle(normalStyle));
|
||||||
blink.play();
|
blink.play();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -670,9 +657,7 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private EventHandler<MouseEvent> mouseClickListener = new EventHandler<MouseEvent>() {
|
private EventHandler<MouseEvent> mouseClickListener = e -> {
|
||||||
@Override
|
|
||||||
public void handle(MouseEvent e) {
|
|
||||||
ThumbCell cell = (ThumbCell) e.getSource();
|
ThumbCell cell = (ThumbCell) e.getSource();
|
||||||
if (e.getButton() == MouseButton.PRIMARY && e.getClickCount() == 2) {
|
if (e.getButton() == MouseButton.PRIMARY && e.getClickCount() == 2) {
|
||||||
cell.setSelected(false);
|
cell.setSelected(false);
|
||||||
|
@ -684,7 +669,6 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
} else if (e.getButton() == MouseButton.PRIMARY) {
|
} else if (e.getButton() == MouseButton.PRIMARY) {
|
||||||
removeSelection();
|
removeSelection();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
protected void onFail(WorkerStateEvent event) {
|
protected void onFail(WorkerStateEvent event) {
|
||||||
|
@ -709,16 +693,13 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void filter() {
|
private void filter() {
|
||||||
Collections.sort(filteredThumbCells, new Comparator<Node>() {
|
Collections.sort(filteredThumbCells, (o1, o2) -> {
|
||||||
@Override
|
ThumbCell c1 = o1;
|
||||||
public int compare(Node o1, Node o2) {
|
ThumbCell c2 = o2;
|
||||||
ThumbCell c1 = (ThumbCell) o1;
|
|
||||||
ThumbCell c2 = (ThumbCell) o2;
|
|
||||||
|
|
||||||
if(c1.getIndex() < c2.getIndex()) return -1;
|
if(c1.getIndex() < c2.getIndex()) return -1;
|
||||||
if(c1.getIndex() > c2.getIndex()) return 1;
|
if(c1.getIndex() > c2.getIndex()) return 1;
|
||||||
return c1.getModel().getName().compareTo(c2.getModel().getName());
|
return c1.getModel().getName().compareTo(c2.getModel().getName());
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (filter == null || filter.isEmpty()) {
|
if (filter == null || filter.isEmpty()) {
|
||||||
|
@ -753,9 +734,9 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void moveActiveRecordingsToFront() {
|
private void moveActiveRecordingsToFront() {
|
||||||
List<Node> thumbsToMove = new ArrayList<>();
|
List<ThumbCell> thumbsToMove = new ArrayList<>();
|
||||||
ObservableList<Node> thumbs = grid.getChildren();
|
ObservableList<Node> thumbs = grid.getChildren();
|
||||||
for (int i = thumbs.size()-1; i > 0; i--) {
|
for (int i = thumbs.size()-1; i >= 0; i--) {
|
||||||
ThumbCell thumb = (ThumbCell) thumbs.get(i);
|
ThumbCell thumb = (ThumbCell) thumbs.get(i);
|
||||||
if(recorder.isTracked(thumb.getModel())) {
|
if(recorder.isTracked(thumb.getModel())) {
|
||||||
thumbs.remove(i);
|
thumbs.remove(i);
|
||||||
|
@ -780,18 +761,23 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
private boolean matches(Model m, String filter) {
|
private boolean matches(Model m, String filter) {
|
||||||
try {
|
try {
|
||||||
String[] tokens = filter.split(" ");
|
String[] tokens = filter.split(" ");
|
||||||
StringBuilder searchTextBuilder = new StringBuilder(m.getName());
|
|
||||||
searchTextBuilder.append(' ');
|
|
||||||
searchTextBuilder.append(m.getDisplayName());
|
|
||||||
searchTextBuilder.append(' ');
|
|
||||||
for (String tag : m.getTags()) {
|
|
||||||
searchTextBuilder.append(tag).append(' ');
|
|
||||||
}
|
|
||||||
int[] resolution = m.getStreamResolution(true);
|
|
||||||
searchTextBuilder.append(resolution[1]);
|
|
||||||
String searchText = searchTextBuilder.toString().trim();
|
|
||||||
boolean tokensMissing = false;
|
boolean tokensMissing = false;
|
||||||
for (String token : tokens) {
|
for (String token : tokens) {
|
||||||
|
if(!modelPropertiesMatchToken(token, m)) {
|
||||||
|
tokensMissing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !tokensMissing;
|
||||||
|
} catch (NumberFormatException | ExecutionException | IOException e) {
|
||||||
|
LOG.error("Error while filtering model list", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean modelPropertiesMatchToken(String token, Model m) throws IOException, ExecutionException {
|
||||||
|
int[] resolution = m.getStreamResolution(true);
|
||||||
|
String searchText = createSearchText(m);
|
||||||
|
boolean tokensMissing = false;
|
||||||
if(token.matches(">\\d+")) {
|
if(token.matches(">\\d+")) {
|
||||||
int res = Integer.parseInt(token.substring(1));
|
int res = Integer.parseInt(token.substring(1));
|
||||||
if(resolution[1] < res) {
|
if(resolution[1] < res) {
|
||||||
|
@ -809,12 +795,20 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
} else if(!searchText.toLowerCase().contains(token.toLowerCase())) {
|
} else if(!searchText.toLowerCase().contains(token.toLowerCase())) {
|
||||||
tokensMissing = true;
|
tokensMissing = true;
|
||||||
}
|
}
|
||||||
|
return tokensMissing;
|
||||||
}
|
}
|
||||||
return !tokensMissing;
|
|
||||||
} catch (NumberFormatException | ExecutionException | IOException e) {
|
private String createSearchText(Model m) throws ExecutionException {
|
||||||
LOG.error("Error while filtering model list", e);
|
StringBuilder searchTextBuilder = new StringBuilder(m.getName());
|
||||||
return false;
|
searchTextBuilder.append(' ');
|
||||||
|
searchTextBuilder.append(m.getDisplayName());
|
||||||
|
searchTextBuilder.append(' ');
|
||||||
|
for (String tag : m.getTags()) {
|
||||||
|
searchTextBuilder.append(tag).append(' ');
|
||||||
}
|
}
|
||||||
|
int[] resolution = m.getStreamResolution(true);
|
||||||
|
searchTextBuilder.append(resolution[1]);
|
||||||
|
return searchTextBuilder.toString().trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRecorder(Recorder recorder) {
|
public void setRecorder(Recorder recorder) {
|
||||||
|
@ -847,7 +841,7 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeSelection() {
|
private void removeSelection() {
|
||||||
while(selectedThumbCells.size() > 0) {
|
while (!selectedThumbCells.isEmpty()) {
|
||||||
selectedThumbCells.get(0).setSelected(false);
|
selectedThumbCells.get(0).setSelected(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
package ctbrec.ui;
|
||||||
|
|
||||||
|
import static ctbrec.ui.controls.Dialogs.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import ctbrec.Model;
|
||||||
|
import ctbrec.sites.Site;
|
||||||
|
import ctbrec.ui.controls.SearchPopover;
|
||||||
|
import ctbrec.ui.controls.SearchPopoverTreeList;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.concurrent.Task;
|
||||||
|
|
||||||
|
public class ThumbOverviewTabSearchTask extends Task<List<Model>> {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(ThumbOverviewTabSearchTask.class);
|
||||||
|
|
||||||
|
private Site site;
|
||||||
|
private SearchPopover popover;
|
||||||
|
private SearchPopoverTreeList popoverTreelist;
|
||||||
|
private String query;
|
||||||
|
|
||||||
|
public ThumbOverviewTabSearchTask(Site site, SearchPopover popover, SearchPopoverTreeList popoverTreelist, String query) {
|
||||||
|
this.site = site;
|
||||||
|
this.popover = popover;
|
||||||
|
this.popoverTreelist = popoverTreelist;
|
||||||
|
this.query = query;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<Model> call() throws Exception {
|
||||||
|
if(site.searchRequiresLogin()) {
|
||||||
|
boolean loggedin = false;
|
||||||
|
try {
|
||||||
|
loggedin = SiteUiFactory.getUi(site).login();
|
||||||
|
} catch (IOException e) {
|
||||||
|
loggedin = false;
|
||||||
|
}
|
||||||
|
if(!loggedin) {
|
||||||
|
showError("Login failed", "Search won't work correctly without login", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return site.search(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void failed() {
|
||||||
|
LOG.error("Search failed", getException());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void succeeded() {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
List<Model> models = getValue();
|
||||||
|
LOG.debug("Search result {} {}", isCancelled(), models);
|
||||||
|
if(models.isEmpty()) {
|
||||||
|
popover.hide();
|
||||||
|
} else {
|
||||||
|
popoverTreelist.getItems().clear();
|
||||||
|
for (Model model : getValue()) {
|
||||||
|
popoverTreelist.getItems().add(model);
|
||||||
|
}
|
||||||
|
popover.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue