Add Camsoda tab with upcoming shows

This commit is contained in:
0xboobface 2018-10-27 18:39:57 +02:00
parent d4bff345a1
commit 07864dc10a
2 changed files with 241 additions and 0 deletions

View File

@ -0,0 +1,240 @@
package ctbrec.sites.camsoda;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.TemporalAccessor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ctbrec.Model;
import ctbrec.recorder.Recorder;
import ctbrec.ui.AutosizeAlert;
import ctbrec.ui.TabSelectionListener;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.Tab;
import javafx.scene.control.TitledPane;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import okhttp3.Request;
import okhttp3.Response;
public class CamsodaShowsTab extends Tab implements TabSelectionListener {
private static final transient Logger LOG = LoggerFactory.getLogger(CamsodaShowsTab.class);
private Camsoda camsoda;
private Recorder recorder;
private VBox showList;
private ProgressIndicator progressIndicator;
public CamsodaShowsTab(Camsoda camsoda, Recorder recorder) {
this.camsoda = camsoda;
this.recorder = recorder;
createGui();
}
private void createGui() {
showList = new VBox(10);
progressIndicator = new ProgressIndicator();
progressIndicator.setPrefSize(100, 100);
setContent(progressIndicator);
setClosable(false);
setText("Shows");
}
@Override
public void selected() {
Task<List<ShowBox>> task = new Task<List<ShowBox>>() {
@Override
protected List<ShowBox> call() throws Exception {
String url = camsoda.getBaseUrl() + "/api/v1/user/model_shows";
Request req = new Request.Builder().url(url).build();
Response response = camsoda.getHttpClient().execute(req);
if (response.isSuccessful()) {
JSONObject json = new JSONObject(response.body().string());
if (json.optInt("success") == 1) {
List<ShowBox> boxes = new ArrayList<>();
JSONArray results = json.getJSONArray("results");
for (int i = 0; i < results.length(); i++) {
JSONObject result = results.getJSONObject(i);
String modelUrl = camsoda.getBaseUrl() + result.getString("url");
String name = modelUrl.substring(modelUrl.lastIndexOf('/') + 1);
Model model = camsoda.createModel(name);
ZonedDateTime startTime = parseUtcTime(result.getString("start"));
ZonedDateTime endTime = parseUtcTime(result.getString("end"));
boxes.add(new ShowBox(model, startTime, endTime));
}
return boxes;
} else {
LOG.error("Couldn't load upcoming camsoda shows. Unexpected response: {}", json.toString());
showErrorDialog("Oh no!", "Couldn't load upcoming CamSoda shows", "Got an unexpected response from server");
}
} else {
response.close();
showErrorDialog("Oh no!", "Couldn't load upcoming CamSoda shows", "Got an unexpected response from server");
LOG.error("Couldn't load upcoming camsoda shows: {} {}", response.code(), response.message());
}
return Collections.emptyList();
}
private ZonedDateTime parseUtcTime(String string) {
DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
TemporalAccessor ta = formatter.parse(string.replace(" UTC", ""));
Instant instant = Instant.from(ta);
return ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
}
@Override
protected void done() {
super.done();
Platform.runLater(() -> {
try {
List<ShowBox> boxes = get();
showList.getChildren().clear();
for (ShowBox showBox : boxes) {
showList.getChildren().add(showBox);
VBox.setMargin(showBox, new Insets(20));
}
} catch (Exception e) {
LOG.error("Couldn't load upcoming camsoda shows", e);
}
setContent(showList);
});
}
};
new Thread(task).start();
}
@Override
public void deselected() {
}
private void showErrorDialog(String title, String head, String msg) {
Platform.runLater(() -> {
Alert alert = new AutosizeAlert(Alert.AlertType.ERROR);
alert.setTitle(title);
alert.setHeaderText(head);
alert.setContentText(msg);
alert.showAndWait();
});
}
private class ShowBox extends TitledPane {
BorderPane root = new BorderPane();
int thumbSize = 200;
public ShowBox(Model model, ZonedDateTime startTime, ZonedDateTime endTime) {
setText(model.getName());
setPrefHeight(268);
setContent(root);
ImageView thumb = new ImageView();
thumb.setPreserveRatio(true);
thumb.setFitHeight(thumbSize);
loadImage(model, thumb);
root.setLeft(new ProgressIndicator());
BorderPane.setMargin(thumb, new Insets(10, 30, 10, 10));
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.MEDIUM);
GridPane grid = new GridPane();
grid.add(createLabel("Start", true), 0, 0);
grid.add(createLabel(formatter.format(startTime), false), 1, 0);
grid.add(createLabel("End", true), 0, 1);
grid.add(createLabel(formatter.format(endTime), false), 1, 1);
Button record = new Button("Record Model");
grid.add(record, 1, 2);
GridPane.setMargin(record, new Insets(10));
root.setCenter(grid);
record.setOnAction((evt) -> {
setCursor(Cursor.WAIT);
new Thread(() -> {
try {
recorder.startRecording(model);
} catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException | IOException e) {
showErrorDialog("Oh no!", "Couldn't add model to the recorder", "Recorder error: " + e.getMessage());
} finally {
Platform.runLater(() ->{
setCursor(Cursor.DEFAULT);
});
}
}).start();
});
loadImage(model, thumb);
}
private void loadImage(Model model, ImageView thumb) {
new Thread(() -> {
try {
String url = camsoda.getBaseUrl() + "/api/v1/user/" + model.getName();
Request detailRequest = new Request.Builder().url(url).build();
Response resp = camsoda.getHttpClient().execute(detailRequest);
if (resp.isSuccessful()) {
JSONObject json = new JSONObject(resp.body().string());
if(json.optBoolean("status") && json.has("user")) {
JSONObject user = json.getJSONObject("user");
if(user.has("settings")) {
JSONObject settings = user.getJSONObject("settings");
if(settings.has("offline_picture")) {
Platform.runLater(() -> {
String imageUrl = settings.getString("offline_picture");
Image img = new Image(imageUrl, 1000, thumbSize, true, true, true);
img.progressProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
if(newValue.doubleValue() == 1.0) {
thumb.setImage(img);
root.setLeft(thumb);
}
}
});
});
}
}
}
}
resp.close();
} catch(Exception e) {
LOG.error("Couldn't load model details", e);
}
}).start();
}
private Node createLabel(String string, boolean bold) {
Label label = new Label(string);
label.setPadding(new Insets(10));
Font def = Font.getDefault();
label.setFont(Font.font(def.getFamily(), bold ? FontWeight.BOLD : FontWeight.NORMAL, 16));
return label;
}
}
}

View File

@ -25,6 +25,7 @@ public class CamsodaTabProvider extends TabProvider {
public List<Tab> getTabs(Scene scene) {
List<Tab> tabs = new ArrayList<>();
tabs.add(createTab("Online", BASE_URI + "/api/v1/browse/online"));
tabs.add(new CamsodaShowsTab(camsoda, recorder));
// ChaturbateFollowedTab followedTab = new ChaturbateFollowedTab("Followed", BASE_URI + "/followed-cams/", chaturbate);
// followedTab.setRecorder(recorder);
// followedTab.setScene(scene);