forked from j62/ctbrec
1
0
Fork 0

Code cleanup

This commit is contained in:
0xb00bface 2021-05-14 19:52:46 +02:00
parent 7d23ebccfe
commit ea062582d4
135 changed files with 1869 additions and 1948 deletions

View File

@ -11,11 +11,7 @@
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-15"> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-15"/>
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"> <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes> <attributes>
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>

View File

@ -12,5 +12,5 @@ org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=15 org.eclipse.jdt.core.compiler.source=15

View File

@ -1,5 +1,7 @@
package ctbrec.docs; package ctbrec.docs;
import static java.nio.charset.StandardCharsets.*;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -7,7 +9,6 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -32,13 +33,13 @@ public abstract class AbstractDocServlet extends HttpServlet {
if(resourceAsStream == null) { if(resourceAsStream == null) {
throw new FileNotFoundException(); throw new FileNotFoundException();
} }
ByteArrayOutputStream out = new ByteArrayOutputStream(); var out = new ByteArrayOutputStream();
int length = 0; var length = 0;
byte[] buffer = new byte[1024]; var buffer = new byte[1024];
while( (length = resourceAsStream.read(buffer)) >= 0 ) { while( (length = resourceAsStream.read(buffer)) >= 0 ) {
out.write(buffer, 0, length); out.write(buffer, 0, length);
} }
return new String(out.toByteArray(), "utf-8"); return new String(out.toByteArray(), UTF_8);
} }
String getHeader() throws IOException { String getHeader() throws IOException {
@ -66,15 +67,15 @@ public abstract class AbstractDocServlet extends HttpServlet {
private void indexJar(URL resource, List<String> pages) throws IOException { private void indexJar(URL resource, List<String> pages) throws IOException {
String fileUrl = resource.getFile(); String fileUrl = resource.getFile();
fileUrl = URLDecoder.decode(fileUrl, StandardCharsets.UTF_8); fileUrl = URLDecoder.decode(fileUrl, UTF_8);
int colon = fileUrl.indexOf(':'); int colon = fileUrl.indexOf(':');
int exclamation = fileUrl.indexOf('!'); int exclamation = fileUrl.indexOf('!');
String jar = fileUrl.substring(colon + 1, exclamation); var jar = fileUrl.substring(colon + 1, exclamation);
String internalFile = fileUrl.substring(exclamation + 2); var internalFile = fileUrl.substring(exclamation + 2);
try (JarFile jarFile = new JarFile(jar)) { try (var jarFile = new JarFile(jar)) {
Enumeration<JarEntry> entries = jarFile.entries(); Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) { while (entries.hasMoreElements()) {
JarEntry jarEntry = entries.nextElement(); var jarEntry = entries.nextElement();
String name = jarEntry.getName(); String name = jarEntry.getName();
if (name.startsWith(internalFile) && name.toLowerCase().endsWith(".md")) { if (name.startsWith(internalFile) && name.toLowerCase().endsWith(".md")) {
pages.add(name.substring(name.lastIndexOf('/') + 1)); pages.add(name.substring(name.lastIndexOf('/') + 1));
@ -84,7 +85,7 @@ public abstract class AbstractDocServlet extends HttpServlet {
} }
private void indexDirectory(URL resource, List<String> pages) { private void indexDirectory(URL resource, List<String> pages) {
File docs = new File(resource.getFile()); var docs = new File(resource.getFile());
String[] files = docs.list((dir, name) -> name.toLowerCase().endsWith(".md")); String[] files = docs.list((dir, name) -> name.toLowerCase().endsWith(".md"));
pages.addAll(Arrays.asList(files)); pages.addAll(Arrays.asList(files));
} }
@ -94,15 +95,19 @@ public abstract class AbstractDocServlet extends HttpServlet {
return loadFile(resource); return loadFile(resource);
} }
protected void error(HttpServletResponse resp, int status, String message) throws IOException { protected void error(HttpServletResponse resp, int status, String message) {
resp.setStatus(status); try {
resp.getWriter().println(getHeader()); resp.setStatus(status);
String html = loadFile("/html/docs/" + status + ".html"); resp.getWriter().println(getHeader());
if(message == null || message.trim().isEmpty()) { String html = loadFile("/html/docs/" + status + ".html");
message = ""; if(message == null || message.trim().isEmpty()) {
message = "";
}
html = html.replace("{message}", message);
resp.getWriter().println(html);
resp.getWriter().println(getFooter());
} catch (IOException e) {
LOG.error("Error while sending error response. Man, his is bad!", e);
} }
html = html.replace("{message}", message);
resp.getWriter().println(html);
resp.getWriter().println(getFooter());
} }
} }

View File

@ -16,40 +16,41 @@ import org.slf4j.LoggerFactory;
import ctbrec.servlet.StaticFileServlet; import ctbrec.servlet.StaticFileServlet;
public class DocServer { public class DocServer {
private static final transient Logger LOG = LoggerFactory.getLogger(DocServer.class); private static final Logger LOG = LoggerFactory.getLogger(DocServer.class);
private static Server server = new Server();
private static volatile boolean started = false; private static volatile boolean started = false;
public synchronized static void start() throws Exception { private DocServer() {}
public static synchronized void start() throws Exception {
if(started) { if(started) {
return; return;
} }
started = true; started = true;
server = new Server(); var server = new Server();
HttpConfiguration config = new HttpConfiguration(); var config = new HttpConfiguration();
config.setSendServerVersion(false); config.setSendServerVersion(false);
ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(config)); var http = new ServerConnector(server, new HttpConnectionFactory(config));
http.setPort(5689); http.setPort(5689);
server.addConnector(http); server.addConnector(http);
ServletHandler handler = new ServletHandler(); var handler = new ServletHandler();
server.setHandler(handler); server.setHandler(handler);
HandlerList handlers = new HandlerList(); var handlers = new HandlerList();
handlers.setHandlers(new Handler[] { handler }); handlers.setHandlers(new Handler[] { handler });
server.setHandler(handlers); server.setHandler(handlers);
MarkdownServlet markdownServlet = new MarkdownServlet(); var markdownServlet = new MarkdownServlet();
ServletHolder holder = new ServletHolder(markdownServlet); var holder = new ServletHolder(markdownServlet);
handler.addServletWithMapping(holder, "/docs/*"); handler.addServletWithMapping(holder, "/docs/*");
AbstractDocServlet searchServlet = new SearchServlet(); AbstractDocServlet searchServlet = new SearchServlet();
holder = new ServletHolder(searchServlet); holder = new ServletHolder(searchServlet);
handler.addServletWithMapping(holder, "/search/*"); handler.addServletWithMapping(holder, "/search/*");
StaticFileServlet staticFileServlet = new StaticFileServlet("/html", false); var staticFileServlet = new StaticFileServlet("/html", false);
holder = new ServletHolder(staticFileServlet); holder = new ServletHolder(staticFileServlet);
handler.addServletWithMapping(holder, "/static/*"); handler.addServletWithMapping(holder, "/static/*");

View File

@ -38,16 +38,18 @@ public class MarkdownServlet extends AbstractDocServlet {
} }
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
error(resp, HttpServletResponse.SC_NOT_FOUND, ""); error(resp, HttpServletResponse.SC_NOT_FOUND, "");
} catch (Exception e) {
error(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "");
} }
} }
private void listPages(HttpServletResponse resp) throws IOException { private void listPages(HttpServletResponse resp) throws IOException {
List<String> pages = getPages(); List<String> pages = getPages();
String html = "<ul>"; var html = new StringBuilder("<ul>");
for (String page : pages) { for (String page : pages) {
html += "<li><a href=\"/docs/" + page + "\">" + page + "</a></li>"; html.append("<li><a href=\"/docs/").append(page).append("\">").append(page).append("</a></li>");
} }
html += "</ul>"; html.append("</ul>");
resp.setStatus(HttpServletResponse.SC_OK); resp.setStatus(HttpServletResponse.SC_OK);
resp.getWriter().println(getHeader()); resp.getWriter().println(getHeader());
resp.getWriter().println(html); resp.getWriter().println(html);
@ -55,8 +57,8 @@ public class MarkdownServlet extends AbstractDocServlet {
} }
private String markdownToHtml(String markdown) { private String markdownToHtml(String markdown) {
MutableDataSet options = new MutableDataSet(); var options = new MutableDataSet();
Parser parser = Parser.builder(options).build(); var parser = Parser.builder(options).build();
HtmlRenderer renderer = HtmlRenderer.builder(options).build(); HtmlRenderer renderer = HtmlRenderer.builder(options).build();
Node document = parser.parse(markdown); Node document = parser.parse(markdown);
String html = renderer.render(document); String html = renderer.render(document);

View File

@ -1,5 +1,7 @@
package ctbrec.docs; package ctbrec.docs;
import static javax.servlet.http.HttpServletResponse.*;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
@ -9,41 +11,55 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.json.JSONArray; import org.json.JSONArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SearchServlet extends AbstractDocServlet { public class SearchServlet extends AbstractDocServlet {
private static final Logger LOG = LoggerFactory.getLogger(SearchServlet.class);
private static final String Q = "term"; private static final String Q = "term";
@Override @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if(req.getParameter(Q) == null) { try {
error(resp, HttpServletResponse.SC_BAD_REQUEST, "Parameter \""+Q+"\" is missing"); if (req.getParameter(Q) == null) {
return; error(resp, HttpServletResponse.SC_BAD_REQUEST, "Parameter \"" + Q + "\" is missing");
return;
}
resp.setStatus(HttpServletResponse.SC_OK);
resp.setContentType("application/json");
var result = new JSONArray();
var pages = getPages();
String q = req.getParameter(Q).toLowerCase();
String[] tokens = q.split("\\s+");
searchPages(result, pages, tokens);
resp.getWriter().println(result.toString());
} catch (Exception e) {
try {
resp.sendError(SC_INTERNAL_SERVER_ERROR, "Internal Server Error");
} catch (IOException ioe) {
LOG.error("Error while sending error response", ioe);
}
} }
}
resp.setStatus(HttpServletResponse.SC_OK); private void searchPages(JSONArray result, List<String> pages, String[] tokens) throws IOException {
resp.setContentType("application/json");
JSONArray result = new JSONArray();
List<String> pages = getPages();
String q = req.getParameter(Q).toLowerCase();
String[] tokens = q.split("\\s+");
for (String page : pages) { for (String page : pages) {
try { try {
String content = loadMarkdown("/docs/" + page).toLowerCase(); String content = loadMarkdown("/docs/" + page).toLowerCase();
boolean allFound = true; var allFound = true;
for (String token : tokens) { for (String token : tokens) {
if(!content.contains(token)) { if (!content.contains(token)) {
allFound = false; allFound = false;
} }
} }
if(allFound) { if (allFound) {
result.put(page); result.put(page);
} }
} catch(FileNotFoundException e) { } catch (FileNotFoundException e) {
// virtual page like index.md -> ignore // virtual page like index.md -> ignore
} }
} }
resp.getWriter().println(result.toString());
} }
} }

View File

@ -34,7 +34,7 @@ public class AutosizeAlert extends Alert {
setResizable(true); setResizable(true);
getDialogPane().setMinHeight(Region.USE_PREF_SIZE); getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
if(parent != null) { if(parent != null) {
Stage stage = (Stage) getDialogPane().getScene().getWindow(); var stage = (Stage) getDialogPane().getScene().getWindow();
stage.getScene().getStylesheets().addAll(parent.getStylesheets()); stage.getScene().getStylesheets().addAll(parent.getStylesheets());
InputStream icon = Dialogs.class.getResourceAsStream("/icon.png"); InputStream icon = Dialogs.class.getResourceAsStream("/icon.png");
stage.getIcons().add(new Image(icon)); stage.getIcons().add(new Image(icon));

View File

@ -86,7 +86,6 @@ import javafx.scene.paint.Color;
import javafx.stage.Stage; import javafx.stage.Stage;
import javafx.stage.WindowEvent; import javafx.stage.WindowEvent;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response;
public class CamrecApplication extends Application { public class CamrecApplication extends Application {
@ -104,7 +103,6 @@ public class CamrecApplication extends Application {
public static HttpClient httpClient; public static HttpClient httpClient;
public static String title; public static String title;
private Stage primaryStage; private Stage primaryStage;
private RecordedTab modelsTab;
private RecordingsTab recordingsTab; private RecordingsTab recordingsTab;
private ScheduledExecutorService scheduler; private ScheduledExecutorService scheduler;
private int activeRecordings = 0; private int activeRecordings = 0;
@ -114,7 +112,7 @@ public class CamrecApplication extends Application {
public void start(Stage primaryStage) throws Exception { public void start(Stage primaryStage) throws Exception {
this.primaryStage = primaryStage; this.primaryStage = primaryStage;
scheduler = Executors.newScheduledThreadPool(1, r -> { scheduler = Executors.newScheduledThreadPool(1, r -> {
Thread t = new Thread(r); var t = new Thread(r);
t.setDaemon(true); t.setDaemon(true);
t.setName("Scheduler"); t.setName("Scheduler");
return t; return t;
@ -172,7 +170,7 @@ public class CamrecApplication extends Application {
private void registerClipboardListener() { private void registerClipboardListener() {
if (config.getSettings().monitorClipboard) { if (config.getSettings().monitorClipboard) {
ClipboardListener clipboardListener = new ClipboardListener(recorder, sites); var clipboardListener = new ClipboardListener(recorder, sites);
scheduler.scheduleAtFixedRate(clipboardListener, 0, 1, TimeUnit.SECONDS); scheduler.scheduleAtFixedRate(clipboardListener, 0, 1, TimeUnit.SECONDS);
} }
} }
@ -209,19 +207,19 @@ public class CamrecApplication extends Application {
int windowWidth = Config.getInstance().getSettings().windowWidth; int windowWidth = Config.getInstance().getSettings().windowWidth;
int windowHeight = Config.getInstance().getSettings().windowHeight; int windowHeight = Config.getInstance().getSettings().windowHeight;
Scene scene = new Scene(rootPane, windowWidth, windowHeight); var scene = new Scene(rootPane, windowWidth, windowHeight);
primaryStage.setScene(scene); primaryStage.setScene(scene);
Dialogs.setScene(scene); Dialogs.setScene(scene);
rootPane.setCenter(tabPane); rootPane.setCenter(tabPane);
rootPane.setBottom(statusBar); rootPane.setBottom(statusBar);
for (Site site : sites) { for (Site site : sites) {
if (site.isEnabled()) { if (site.isEnabled()) {
SiteTab siteTab = new SiteTab(site, scene); var siteTab = new SiteTab(site, scene);
tabPane.getTabs().add(siteTab); tabPane.getTabs().add(siteTab);
} }
} }
modelsTab = new RecordedTab(recorder, sites); var modelsTab = new RecordedTab(recorder, sites);
tabPane.getTabs().add(modelsTab); tabPane.getTabs().add(modelsTab);
recordingsTab = new RecordingsTab("Recordings", recorder, config); recordingsTab = new RecordingsTab("Recordings", recorder, config);
tabPane.getTabs().add(recordingsTab); tabPane.getTabs().add(recordingsTab);
@ -236,7 +234,7 @@ public class CamrecApplication extends Application {
switchToStartTab(); switchToStartTab();
writeColorSchemeStyleSheet(); writeColorSchemeStyleSheet();
Color base = Color.web(Config.getInstance().getSettings().colorBase); var base = Color.web(Config.getInstance().getSettings().colorBase);
if (!base.equals(Color.WHITE)) { if (!base.equals(Color.WHITE)) {
loadStyleSheet(primaryStage, "color.css"); loadStyleSheet(primaryStage, "color.css");
} }
@ -308,7 +306,7 @@ public class CamrecApplication extends Application {
} }
// check for active recordings // check for active recordings
boolean shutdownNow = false; var shutdownNow = false;
if (config.getSettings().localRecording) { if (config.getSettings().localRecording) {
try { try {
if (!recorder.getCurrentlyRecording().isEmpty()) { if (!recorder.getCurrentlyRecording().isEmpty()) {
@ -374,7 +372,7 @@ public class CamrecApplication extends Application {
private void registerAlertSystem() { private void registerAlertSystem() {
for (EventHandlerConfiguration eventHandlerConfig : Config.getInstance().getSettings().eventHandlers) { for (EventHandlerConfiguration eventHandlerConfig : Config.getInstance().getSettings().eventHandlers) {
EventHandler handler = new EventHandler(eventHandlerConfig); var handler = new EventHandler(eventHandlerConfig);
EventBusHolder.register(handler); EventBusHolder.register(handler);
LOG.debug("Registered event handler for {} {}", eventHandlerConfig.getEvent(), eventHandlerConfig.getName()); LOG.debug("Registered event handler for {} {}", eventHandlerConfig.getEvent(), eventHandlerConfig.getName());
} }
@ -428,13 +426,13 @@ public class CamrecApplication extends Application {
bytesPerSecond = 0; bytesPerSecond = 0;
} }
String humanReadable = ByteUnitFormatter.format(bytesPerSecond); String humanReadable = ByteUnitFormatter.format(bytesPerSecond);
String status = String.format("Recording %s / %s models @ %s/s", activeRecordings, recorder.getModelCount(), humanReadable); var status = String.format("Recording %s / %s models @ %s/s", activeRecordings, recorder.getModelCount(), humanReadable);
Platform.runLater(() -> statusLabel.setText(status)); Platform.runLater(() -> statusLabel.setText(status));
} }
private void writeColorSchemeStyleSheet() { private void writeColorSchemeStyleSheet() {
File colorCss = new File(Config.getInstance().getConfigDir(), "color.css"); var colorCss = new File(Config.getInstance().getConfigDir(), "color.css");
try (FileOutputStream fos = new FileOutputStream(colorCss)) { try (var fos = new FileOutputStream(colorCss)) {
String content = ".root {\n" + " -fx-base: " + Config.getInstance().getSettings().colorBase + ";\n" + " -fx-accent: " String content = ".root {\n" + " -fx-base: " + Config.getInstance().getSettings().colorBase + ";\n" + " -fx-accent: "
+ Config.getInstance().getSettings().colorAccent + ";\n" + " -fx-default-button: -fx-accent;\n" + " -fx-focus-color: -fx-accent;\n" + Config.getInstance().getSettings().colorAccent + ";\n" + " -fx-default-button: -fx-accent;\n" + " -fx-focus-color: -fx-accent;\n"
+ " -fx-control-inner-background-alt: derive(-fx-base, 95%);\n" + "}"; + " -fx-control-inner-background-alt: derive(-fx-base, 95%);\n" + "}";
@ -445,7 +443,7 @@ public class CamrecApplication extends Application {
} }
public static void loadStyleSheet(Stage primaryStage, String filename) { public static void loadStyleSheet(Stage primaryStage, String filename) {
File css = new File(Config.getInstance().getConfigDir(), filename); var css = new File(Config.getInstance().getConfigDir(), filename);
if (css.exists() && css.isFile()) { if (css.exists() && css.isFile()) {
primaryStage.getScene().getStylesheets().add(css.toURI().toString()); primaryStage.getScene().getStylesheets().add(css.toURI().toString());
} }
@ -509,20 +507,20 @@ public class CamrecApplication extends Application {
} }
private void checkForUpdates() { private void checkForUpdates() {
Thread updateCheck = new Thread(() -> { var updateCheck = new Thread(() -> {
String url = "https://pastebin.com/raw/mUxtKzyB"; var url = "https://pastebin.com/raw/mUxtKzyB";
Request request = new Request.Builder().url(url).build(); var request = new Request.Builder().url(url).build();
try (Response response = httpClient.execute(request)) { try (var response = httpClient.execute(request)) {
String body = response.body().string(); var body = response.body().string();
LOG.trace("Version check respone: {}", body); LOG.trace("Version check respone: {}", body);
if (response.isSuccessful()) { if (response.isSuccessful()) {
Moshi moshi = new Moshi.Builder().build(); var moshi = new Moshi.Builder().build();
Type type = Types.newParameterizedType(List.class, Release.class); Type type = Types.newParameterizedType(List.class, Release.class);
JsonAdapter<List<Release>> adapter = moshi.adapter(type); JsonAdapter<List<Release>> adapter = moshi.adapter(type);
List<Release> releases = adapter.fromJson(body); List<Release> releases = adapter.fromJson(body);
Release latest = releases.get(0); var latest = releases.get(0);
Version latestVersion = latest.getVersion(); var latestVersion = latest.getVersion();
Version ctbrecVersion = getVersion(); var ctbrecVersion = getVersion();
if (latestVersion.compareTo(ctbrecVersion) > 0) { if (latestVersion.compareTo(ctbrecVersion) > 0) {
LOG.debug("Update available {} < {}", ctbrecVersion, latestVersion); LOG.debug("Update available {} < {}", ctbrecVersion, latestVersion);
Platform.runLater(() -> tabPane.getTabs().add(new UpdateTab(latest))); Platform.runLater(() -> tabPane.getTabs().add(new UpdateTab(latest)));
@ -546,8 +544,8 @@ public class CamrecApplication extends Application {
return Version.of("0.0.0-DEV"); return Version.of("0.0.0-DEV");
} else { } else {
try (InputStream is = CamrecApplication.class.getClassLoader().getResourceAsStream("version")) { try (InputStream is = CamrecApplication.class.getClassLoader().getResourceAsStream("version")) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is)); var reader = new BufferedReader(new InputStreamReader(is));
String versionString = reader.readLine(); var versionString = reader.readLine();
return Version.of(versionString); return Version.of(versionString);
} }
} }

View File

@ -1,19 +1,19 @@
package ctbrec.ui; package ctbrec.ui;
import ctbrec.Model;
import ctbrec.recorder.Recorder;
import ctbrec.sites.Site;
import javafx.application.Platform;
import javafx.scene.input.Clipboard;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ctbrec.recorder.Recorder;
import ctbrec.sites.Site;
import javafx.application.Platform;
import javafx.scene.input.Clipboard;
public class ClipboardListener implements Runnable { public class ClipboardListener implements Runnable {
private static final Logger LOG = LoggerFactory.getLogger(ClipboardListener.class); private static final Logger LOG = LoggerFactory.getLogger(ClipboardListener.class);
@ -50,7 +50,7 @@ public class ClipboardListener implements Runnable {
private void addModelIfUrlMatches(String url) { private void addModelIfUrlMatches(String url) {
for (Site site : sites) { for (Site site : sites) {
Model m = site.createModelFromUrl(url); var m = site.createModelFromUrl(url);
if (m != null) { if (m != null) {
try { try {
recorder.addModel(m); recorder.addModel(m);

View File

@ -2,7 +2,6 @@ package ctbrec.ui;
import java.awt.AWTException; import java.awt.AWTException;
import java.awt.Desktop; import java.awt.Desktop;
import java.awt.Image;
import java.awt.MenuItem; import java.awt.MenuItem;
import java.awt.PopupMenu; import java.awt.PopupMenu;
import java.awt.SystemTray; import java.awt.SystemTray;
@ -65,8 +64,8 @@ public class DesktopIntegration {
} }
// try external helpers // try external helpers
String[] externalHelpers = { "kde-open5", "kde-open", "gnome-open", "xdg-open" }; var externalHelpers = new String[] { "kde-open5", "kde-open", "gnome-open", "xdg-open" };
Runtime rt = Runtime.getRuntime(); var rt = Runtime.getRuntime();
for (String helper : externalHelpers) { for (String helper : externalHelpers) {
try { try {
rt.exec(helper + " " + uri); rt.exec(helper + " " + uri);
@ -80,9 +79,9 @@ public class DesktopIntegration {
Alert info = new AutosizeAlert(Alert.AlertType.ERROR); Alert info = new AutosizeAlert(Alert.AlertType.ERROR);
info.setTitle("Open URL"); info.setTitle("Open URL");
info.setContentText("Couldn't open URL"); info.setContentText("Couldn't open URL");
BorderPane pane = new BorderPane(); var pane = new BorderPane();
pane.setTop(new Label()); pane.setTop(new Label());
TextField urlField = new TextField(uri); var urlField = new TextField(uri);
urlField.setPadding(new Insets(10)); urlField.setPadding(new Insets(10));
urlField.setEditable(false); urlField.setEditable(false);
pane.setCenter(urlField); pane.setCenter(urlField);
@ -100,8 +99,8 @@ public class DesktopIntegration {
} }
// try external helpers // try external helpers
String[] externalHelpers = { "kde-open5", "kde-open", "gnome-open", "xdg-open" }; var externalHelpers = new String[] { "kde-open5", "kde-open", "gnome-open", "xdg-open" };
Runtime rt = Runtime.getRuntime(); var rt = Runtime.getRuntime();
for (String helper : externalHelpers) { for (String helper : externalHelpers) {
try { try {
rt.exec(helper + " " + f.getAbsolutePath()); rt.exec(helper + " " + f.getAbsolutePath());
@ -115,9 +114,9 @@ public class DesktopIntegration {
Alert info = new AutosizeAlert(Alert.AlertType.ERROR); Alert info = new AutosizeAlert(Alert.AlertType.ERROR);
info.setTitle("Open file"); info.setTitle("Open file");
info.setContentText("Couldn't open file"); info.setContentText("Couldn't open file");
BorderPane pane = new BorderPane(); var pane = new BorderPane();
pane.setTop(new Label()); pane.setTop(new Label());
TextField urlField = new TextField(f.toString()); var urlField = new TextField(f.toString());
urlField.setPadding(new Insets(10)); urlField.setPadding(new Insets(10));
urlField.setEditable(false); urlField.setEditable(false);
pane.setCenter(urlField); pane.setCenter(urlField);
@ -189,7 +188,7 @@ public class DesktopIntegration {
if (tray == null) { if (tray == null) {
String title = CamrecApplication.title; String title = CamrecApplication.title;
tray = SystemTray.getSystemTray(); tray = SystemTray.getSystemTray();
Image image = Toolkit.getDefaultToolkit().createImage(DesktopIntegration.class.getResource("/icon64.png")); var image = Toolkit.getDefaultToolkit().createImage(DesktopIntegration.class.getResource("/icon64.png"));
PopupMenu menu = createTrayContextMenu(stage); PopupMenu menu = createTrayContextMenu(stage);
trayIcon = new TrayIcon(image, title, menu); trayIcon = new TrayIcon(image, title, menu);
@ -217,12 +216,12 @@ public class DesktopIntegration {
} }
private static PopupMenu createTrayContextMenu(Stage stage) { private static PopupMenu createTrayContextMenu(Stage stage) {
PopupMenu menu = new PopupMenu(); var menu = new PopupMenu();
MenuItem show = new MenuItem("Show"); var show = new MenuItem("Show");
show.addActionListener(evt -> restoreStage(stage)); show.addActionListener(evt -> restoreStage(stage));
menu.add(show); menu.add(show);
menu.addSeparator(); menu.addSeparator();
MenuItem pauseRecording = new MenuItem("Pause recording"); var pauseRecording = new MenuItem("Pause recording");
pauseRecording.addActionListener(evt -> { pauseRecording.addActionListener(evt -> {
try { try {
recorder.pause(); recorder.pause();
@ -231,7 +230,7 @@ public class DesktopIntegration {
} }
}); });
menu.add(pauseRecording); menu.add(pauseRecording);
MenuItem resumeRecording = new MenuItem("Resume recording"); var resumeRecording = new MenuItem("Resume recording");
resumeRecording.addActionListener(evt -> { resumeRecording.addActionListener(evt -> {
try { try {
recorder.resume(); recorder.resume();
@ -241,8 +240,8 @@ public class DesktopIntegration {
}); });
menu.add(resumeRecording); menu.add(resumeRecording);
menu.addSeparator(); menu.addSeparator();
MenuItem exit = new MenuItem("Exit"); var exit = new MenuItem("Exit");
exit.addActionListener(evt -> exit(stage)); exit.addActionListener(evt -> exit());
menu.add(exit); menu.add(exit);
return menu; return menu;
} }
@ -266,7 +265,7 @@ public class DesktopIntegration {
}); });
} }
private static void exit(Stage stage) { private static void exit() {
EventBusHolder.BUS.post(Map.of("event", "shutdown")); EventBusHolder.BUS.post(Map.of("event", "shutdown"));
} }

View File

@ -20,7 +20,6 @@ import org.slf4j.LoggerFactory;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.OS; import ctbrec.OS;
import ctbrec.Settings.ProxyType;
import ctbrec.io.StreamRedirector; import ctbrec.io.StreamRedirector;
public class ExternalBrowser implements AutoCloseable { public class ExternalBrowser implements AutoCloseable {
@ -50,7 +49,7 @@ public class ExternalBrowser implements AutoCloseable {
addProxyConfig(jsonConfig.getJSONObject("config")); addProxyConfig(jsonConfig.getJSONObject("config"));
File configDir = new File(Config.getInstance().getConfigDir(), "ctbrec-minimal-browser"); var configDir = new File(Config.getInstance().getConfigDir(), "ctbrec-minimal-browser");
String[] cmdline = OS.getBrowserCommand(configDir.getCanonicalPath()); String[] cmdline = OS.getBrowserCommand(configDir.getCanonicalPath());
Process p = new ProcessBuilder(cmdline).start(); Process p = new ProcessBuilder(cmdline).start();
if (LOG.isTraceEnabled()) { if (LOG.isTraceEnabled()) {
@ -91,7 +90,7 @@ public class ExternalBrowser implements AutoCloseable {
} }
private void connectToRemoteControlSocket() throws IOException { private void connectToRemoteControlSocket() throws IOException {
for (int i = 0; i < 20; i++) { for (var i = 0; i < 20; i++) {
try { try {
socket = new Socket("localhost", 3202); socket = new Socket("localhost", 3202);
in = socket.getInputStream(); in = socket.getInputStream();
@ -117,7 +116,7 @@ public class ExternalBrowser implements AutoCloseable {
} }
public void executeJavaScript(String javaScript) throws IOException { public void executeJavaScript(String javaScript) throws IOException {
JSONObject script = new JSONObject(); var script = new JSONObject();
script.put("execute", javaScript); script.put("execute", javaScript);
out.write(script.toString().getBytes(UTF_8)); out.write(script.toString().getBytes(UTF_8));
out.write('\n'); out.write('\n');
@ -138,7 +137,7 @@ public class ExternalBrowser implements AutoCloseable {
private void readBrowserOutput() { private void readBrowserOutput() {
LOG.debug("Browser output reader started"); LOG.debug("Browser output reader started");
try (BufferedReader br = new BufferedReader(new InputStreamReader(in))) { try (var br = new BufferedReader(new InputStreamReader(in))) {
String line; String line;
synchronized (browserReadyLock) { synchronized (browserReadyLock) {
browserReady = true; browserReady = true;
@ -164,10 +163,10 @@ public class ExternalBrowser implements AutoCloseable {
} }
private void addProxyConfig(JSONObject jsonConfig) { private void addProxyConfig(JSONObject jsonConfig) {
ProxyType proxyType = Config.getInstance().getSettings().proxyType; var proxyType = Config.getInstance().getSettings().proxyType;
switch (proxyType) { switch (proxyType) {
case HTTP: case HTTP:
JSONObject proxy = new JSONObject(); var proxy = new JSONObject();
proxy.put("address", proxy.put("address",
"http=" + Config.getInstance().getSettings().proxyHost + ':' + Config.getInstance().getSettings().proxyPort "http=" + Config.getInstance().getSettings().proxyHost + ':' + Config.getInstance().getSettings().proxyPort
+ ";https=" + Config.getInstance().getSettings().proxyHost + ':' + Config.getInstance().getSettings().proxyPort); + ";https=" + Config.getInstance().getSettings().proxyHost + ':' + Config.getInstance().getSettings().proxyPort);

View File

@ -12,7 +12,6 @@ import org.slf4j.LoggerFactory;
import ctbrec.io.HttpClient; import ctbrec.io.HttpClient;
import ctbrec.recorder.ProgressListener; import ctbrec.recorder.ProgressListener;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response;
public class FileDownload { public class FileDownload {
@ -28,13 +27,13 @@ public class FileDownload {
public void start(URL url, File target) throws IOException { public void start(URL url, File target) throws IOException {
LOG.trace("Downloading file {} to {}", url, target); LOG.trace("Downloading file {} to {}", url, target);
Request request = new Request.Builder().url(url).addHeader("connection", "keep-alive").build(); var request = new Request.Builder().url(url).addHeader("connection", "keep-alive").build();
Response response = httpClient.execute(request); var response = httpClient.execute(request);
long fileSize = Long.parseLong(response.header("Content-Length", String.valueOf(Long.MAX_VALUE))); var fileSize = Long.parseLong(response.header("Content-Length", String.valueOf(Long.MAX_VALUE)));
InputStream in = null; InputStream in = null;
try (FileOutputStream fos = new FileOutputStream(target)) { try (var fos = new FileOutputStream(target)) {
in = response.body().byteStream(); in = response.body().byteStream();
byte[] b = new byte[1024 * 100]; var b = new byte[1024 * 100];
long totalBytesRead = 0; long totalBytesRead = 0;
int length = -1; int length = -1;
while ((length = in.read(b)) >= 0) { while ((length = in.read(b)) >= 0) {

View File

@ -23,54 +23,63 @@ public class CheckModelAccountAction {
private Recorder recorder; private Recorder recorder;
private String buttonText;
public CheckModelAccountAction(Button b, Recorder recorder) { public CheckModelAccountAction(Button b, Recorder recorder) {
this.b = b; this.b = b;
this.recorder = recorder; this.recorder = recorder;
buttonText = b.getText();
} }
public void execute(Predicate<Model> filter) { public void execute(Predicate<Model> filter) {
String buttonText = b.getText();
b.setDisable(true); b.setDisable(true);
Runnable checker = (() -> { Runnable checker = (() -> {
List<Model> deletedAccounts = new ArrayList<>(); List<Model> deletedAccounts = new ArrayList<>();
try { try {
List<Model> models = recorder.getModels().stream() // checkModelAccounts(filter, deletedAccounts);
.filter(filter) //
.collect(Collectors.toList());
int total = models.size();
for (int i = 0; i < total; i++) {
final int counter = i+1;
Platform.runLater(() -> b.setText(buttonText + ' ' + counter + '/' + total));
Model modelToCheck = models.get(i);
try {
if (!modelToCheck.exists()) {
deletedAccounts.add(modelToCheck);
}
} catch (IOException e) {
LOG.warn("Couldn't check, if model account still exists", e);
}
}
} finally { } finally {
Platform.runLater(() -> { showResult(deletedAccounts);
b.setDisable(false);
b.setText(buttonText);
if (!deletedAccounts.isEmpty()) {
StringBuilder sb = new StringBuilder();
for (Model deletedModel : deletedAccounts) {
String name = deletedModel.getDisplayName() + " ".repeat(30);
name = name.substring(0, 30);
sb.append(name).append(' ').append('(').append(deletedModel.getUrl()).append(')').append('\n');
}
boolean remove = Dialogs.showConfirmDialog("Deleted Accounts", sb.toString(),
"The following accounts seem to have been deleted. Do you want to remove them?", b.getScene());
if (remove) {
new StopRecordingAction(b, deletedAccounts, recorder).execute();
}
}
});
} }
}); });
GlobalThreadPool.submit(checker); GlobalThreadPool.submit(checker);
} }
private void showResult(List<Model> deletedAccounts) {
Platform.runLater(() -> {
b.setDisable(false);
b.setText(buttonText);
if (!deletedAccounts.isEmpty()) {
var sb = new StringBuilder();
for (Model deletedModel : deletedAccounts) {
String name = deletedModel.getDisplayName() + " ".repeat(30);
name = name.substring(0, 30);
sb.append(name).append(' ').append('(').append(deletedModel.getUrl()).append(')').append('\n');
}
boolean remove = Dialogs.showConfirmDialog("Deleted Accounts", sb.toString(),
"The following accounts seem to have been deleted. Do you want to remove them?", b.getScene());
if (remove) {
new StopRecordingAction(b, deletedAccounts, recorder).execute();
}
}
});
}
private void checkModelAccounts(Predicate<Model> filter, List<Model> deletedAccounts) {
List<Model> models = recorder.getModels().stream() //
.filter(filter) //
.collect(Collectors.toList());
int total = models.size();
for (var i = 0; i < total; i++) {
final int counter = i+1;
Platform.runLater(() -> b.setText(buttonText + ' ' + counter + '/' + total));
var modelToCheck = models.get(i);
try {
if (!modelToCheck.exists()) {
deletedAccounts.add(modelToCheck);
}
} catch (IOException e) {
LOG.warn("Couldn't check, if model account still exists", e);
}
}
}
} }

View File

@ -5,7 +5,6 @@ import java.util.function.Consumer;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.Settings;
import ctbrec.recorder.Recorder; import ctbrec.recorder.Recorder;
import ctbrec.ui.JavaFxModel; import ctbrec.ui.JavaFxModel;
import ctbrec.ui.controls.Dialogs; import ctbrec.ui.controls.Dialogs;
@ -29,8 +28,8 @@ public class IgnoreModelsAction {
} }
public void execute(Consumer<Model> callback) { public void execute(Consumer<Model> callback) {
Settings settings = Config.getInstance().getSettings(); var settings = Config.getInstance().getSettings();
boolean confirmed = true; var confirmed = true;
if (settings.confirmationForDangerousActions) { if (settings.confirmationForDangerousActions) {
int n = selectedModels.size(); int n = selectedModels.size();
String plural = n > 1 ? "s" : ""; String plural = n > 1 ? "s" : "";
@ -39,7 +38,7 @@ public class IgnoreModelsAction {
} }
if (confirmed) { if (confirmed) {
for (Model model : selectedModels) { for (Model model : selectedModels) {
Model modelToIgnore = unwrap(model); var modelToIgnore = unwrap(model);
settings.ignoredModels.add(modelToIgnore.getUrl()); settings.ignoredModels.add(modelToIgnore.getUrl());
} }
if (withRemoveDialog) { if (withRemoveDialog) {

View File

@ -24,7 +24,7 @@ public class OpenRecordingsDir {
public void execute() { public void execute() {
source.setCursor(Cursor.WAIT); source.setCursor(Cursor.WAIT);
File fileForRecording = Config.getInstance().getFileForRecording(selectedModel, ".mp4", Instant.now()); var fileForRecording = Config.getInstance().getFileForRecording(selectedModel, ".mp4", Instant.now());
final File dir = getModelDirectory(fileForRecording); final File dir = getModelDirectory(fileForRecording);
if (dir.exists()) { if (dir.exists()) {
GlobalThreadPool.submit(() -> DesktopIntegration.open(dir)); GlobalThreadPool.submit(() -> DesktopIntegration.open(dir));
@ -35,7 +35,7 @@ public class OpenRecordingsDir {
} }
private File getModelDirectory(File fileForRecording) { private File getModelDirectory(File fileForRecording) {
File dir = fileForRecording.getParentFile(); var dir = fileForRecording.getParentFile();
if (Config.getInstance().getSettings().recordingsDirStructure == DirectoryStructure.ONE_PER_RECORDING) { if (Config.getInstance().getSettings().recordingsDirStructure == DirectoryStructure.ONE_PER_RECORDING) {
dir = dir.getParentFile(); dir = dir.getParentFile();
} }

View File

@ -2,7 +2,6 @@ package ctbrec.ui.action;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.ui.SiteUI;
import ctbrec.ui.SiteUiFactory; import ctbrec.ui.SiteUiFactory;
import ctbrec.ui.controls.Toast; import ctbrec.ui.controls.Toast;
import javafx.application.Platform; import javafx.application.Platform;
@ -21,8 +20,8 @@ public class PlayAction {
public void execute() { public void execute() {
source.setCursor(Cursor.WAIT); source.setCursor(Cursor.WAIT);
Thread t = new Thread(() -> { var t = new Thread(() -> {
SiteUI siteUI = SiteUiFactory.getUi(selectedModel.getSite()); var siteUI = SiteUiFactory.getUi(selectedModel.getSite());
boolean started = siteUI.play(selectedModel); boolean started = siteUI.play(selectedModel);
Platform.runLater(() -> { Platform.runLater(() -> {
if (started && Config.getInstance().getSettings().showPlayerStarting) { if (started && Config.getInstance().getSettings().showPlayerStarting) {

View File

@ -27,7 +27,7 @@ public class RemoveTimeLimitAction {
public CompletableFuture<Boolean> execute() { public CompletableFuture<Boolean> execute() {
source.setCursor(Cursor.WAIT); source.setCursor(Cursor.WAIT);
Instant unlimited = Instant.ofEpochMilli(Model.RECORD_INDEFINITELY); var unlimited = Instant.ofEpochMilli(Model.RECORD_INDEFINITELY);
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
try { try {
selectedModel.setRecordUntil(unlimited); selectedModel.setRecordUntil(unlimited);

View File

@ -1,18 +1,18 @@
package ctbrec.ui.action; package ctbrec.ui.action;
import java.util.List;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.recorder.Recorder; import ctbrec.recorder.Recorder;
import ctbrec.ui.controls.Dialogs; import ctbrec.ui.controls.Dialogs;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.scene.Node; import javafx.scene.Node;
import java.util.List;
public class StartRecordingAction extends ModelMassEditAction { public class StartRecordingAction extends ModelMassEditAction {
public StartRecordingAction(Node source, List<? extends Model> models, Recorder recorder) { public StartRecordingAction(Node source, List<? extends Model> models, Recorder recorder) {
super(source, models); super(source, models);
action = (m) -> { action = m -> {
try { try {
recorder.addModel(m); recorder.addModel(m);
} catch (Exception e) { } catch (Exception e) {

View File

@ -11,8 +11,6 @@ import ctbrec.ui.AutosizeAlert;
import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty; import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener; import javafx.beans.value.ChangeListener;
import javafx.geometry.Point2D;
import javafx.scene.Node;
import javafx.scene.control.Alert; import javafx.scene.control.Alert;
import javafx.scene.control.Button; import javafx.scene.control.Button;
import javafx.scene.control.TextField; import javafx.scene.control.TextField;
@ -36,7 +34,7 @@ public abstract class AbstractFileSelectionBox extends HBox {
protected boolean allowEmptyValue = false; protected boolean allowEmptyValue = false;
private Tooltip validationError = new Tooltip(); private Tooltip validationError = new Tooltip();
public AbstractFileSelectionBox() { protected AbstractFileSelectionBox() {
super(5); super(5);
fileInput = new TextField(); fileInput = new TextField();
fileInput.textProperty().addListener(textListener()); fileInput.textProperty().addListener(textListener());
@ -45,7 +43,7 @@ public abstract class AbstractFileSelectionBox extends HBox {
validationError.hide(); validationError.hide();
} }
}); });
Node browse = createBrowseButton(); var browse = createBrowseButton();
browse.disableProperty().bind(disableProperty()); browse.disableProperty().bind(disableProperty());
fileInput.disableProperty().bind(disableProperty()); fileInput.disableProperty().bind(disableProperty());
fileInput.textProperty().bindBidirectional(fileProperty); fileInput.textProperty().bindBidirectional(fileProperty);
@ -63,14 +61,14 @@ public abstract class AbstractFileSelectionBox extends HBox {
}); });
} }
public AbstractFileSelectionBox(String initialValue) { protected AbstractFileSelectionBox(String initialValue) {
this(); this();
fileInput.setText(initialValue); fileInput.setText(initialValue);
} }
private ChangeListener<? super String> textListener() { private ChangeListener<? super String> textListener() {
return (obs, o, n) -> { return (obs, o, n) -> {
String input = fileInput.getText(); var input = fileInput.getText();
if (StringUtil.isBlank(input)) { if (StringUtil.isBlank(input)) {
if (allowEmptyValue) { if (allowEmptyValue) {
fileProperty.set(""); fileProperty.set("");
@ -78,19 +76,19 @@ public abstract class AbstractFileSelectionBox extends HBox {
return; return;
} }
} else { } else {
File program = new File(input); var program = new File(input);
setFile(program); setFile(program);
} }
}; };
} }
protected void setFile(File file) { protected void setFile(File file) {
String msg = validate(file); var msg = validate(file);
if (msg != null) { if (msg != null) {
fileInput.setBorder(new Border(new BorderStroke(Color.RED, BorderStrokeStyle.DASHED, new CornerRadii(2), new BorderWidths(2)))); fileInput.setBorder(new Border(new BorderStroke(Color.RED, BorderStrokeStyle.DASHED, new CornerRadii(2), new BorderWidths(2))));
validationError.setText(msg); validationError.setText(msg);
fileInput.setTooltip(validationError); fileInput.setTooltip(validationError);
Point2D p = fileInput.localToScreen(fileInput.getTranslateY(), fileInput.getTranslateY()); var p = fileInput.localToScreen(fileInput.getTranslateY(), fileInput.getTranslateY());
if (!validationError.isShowing() && getScene() != null) { if (!validationError.isShowing() && getScene() != null) {
validationError.show(getScene().getWindow(), p.getX(), p.getY() + fileInput.getHeight() + 4); validationError.show(getScene().getWindow(), p.getX(), p.getY() + fileInput.getHeight() + 4);
} }
@ -123,7 +121,7 @@ public abstract class AbstractFileSelectionBox extends HBox {
} }
private Button createBrowseButton() { private Button createBrowseButton() {
Button button = new Button("Select"); var button = new Button("Select");
button.setOnAction(e -> choose()); button.setOnAction(e -> choose());
button.prefHeightProperty().bind(this.heightProperty()); button.prefHeightProperty().bind(this.heightProperty());
button.prefWidthProperty().set(70); button.prefWidthProperty().set(70);
@ -131,14 +129,14 @@ public abstract class AbstractFileSelectionBox extends HBox {
} }
protected void choose() { protected void choose() {
FileChooser chooser = new FileChooser(); var chooser = new FileChooser();
File program = chooser.showOpenDialog(null); var program = chooser.showOpenDialog(null);
if (program != null) { if (program != null) {
try { try {
fileInput.setText(program.getCanonicalPath()); fileInput.setText(program.getCanonicalPath());
} catch (IOException e1) { } catch (IOException e1) {
LOG.error("Couldn't determine path", e1); LOG.error("Couldn't determine path", e1);
Alert alert = new AutosizeAlert(Alert.AlertType.ERROR, getScene()); var alert = new AutosizeAlert(Alert.AlertType.ERROR, getScene());
alert.setTitle("Whoopsie"); alert.setTitle("Whoopsie");
alert.setContentText("Couldn't determine path"); alert.setContentText("Couldn't determine path");
alert.showAndWait(); alert.showAndWait();

View File

@ -19,8 +19,8 @@ public class DateTimeCellFactory<T> implements Callback<TableColumn<T, Instant>,
if (empty || item == null) { if (empty || item == null) {
setText(""); setText("");
} else { } else {
LocalDateTime dateTime = LocalDateTime.ofInstant(item, ZoneId.systemDefault()); var dateTime = LocalDateTime.ofInstant(item, ZoneId.systemDefault());
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT); var formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
String formattedDateTime = formatter.format(dateTime); String formattedDateTime = formatter.format(dateTime);
setText(item.equals(Instant.EPOCH) ? "" : formattedDateTime); setText(item.equals(Instant.EPOCH) ? "" : formattedDateTime);
} }

View File

@ -12,14 +12,14 @@ public class DirectorySelectionBox extends AbstractFileSelectionBox {
@Override @Override
protected void choose() { protected void choose() {
DirectoryChooser chooser = new DirectoryChooser(); var chooser = new DirectoryChooser();
String preselection = Optional.ofNullable(fileProperty().get()).orElse("."); var preselection = Optional.ofNullable(fileProperty().get()).orElse(".");
File currentDir = new File(preselection); var currentDir = new File(preselection);
if (currentDir.exists() && currentDir.isDirectory()) { if (currentDir.exists() && currentDir.isDirectory()) {
chooser.setInitialDirectory(currentDir); chooser.setInitialDirectory(currentDir);
} }
File selectedDir = chooser.showDialog(null); File selectedDir = chooser.showDialog(null);
if(selectedDir != null) { if (selectedDir != null) {
fileInput.setText(selectedDir.getAbsolutePath()); fileInput.setText(selectedDir.getAbsolutePath());
setFile(selectedDir); setFile(selectedDir);
} }
@ -27,12 +27,12 @@ public class DirectorySelectionBox extends AbstractFileSelectionBox {
@Override @Override
protected String validate(File file) { protected String validate(File file) {
if(isDisabled()) { if (isDisabled()) {
return null; return null;
} }
String msg = super.validate(file); String msg = super.validate(file);
if(msg != null) { if (msg != null) {
return msg; return msg;
} else if (!file.isDirectory()) { } else if (!file.isDirectory()) {
return "This is not a directory"; return "This is not a directory";

View File

@ -10,9 +10,9 @@ public class FasterVerticalScrollPaneSkin extends ScrollPaneSkin {
super(scrollPane); super(scrollPane);
getSkinnable().addEventFilter(ScrollEvent.SCROLL, event -> { getSkinnable().addEventFilter(ScrollEvent.SCROLL, event -> {
double ratio = scrollPane.getViewportBounds().getHeight() / scrollPane.getContent().getBoundsInLocal().getHeight(); var ratio = scrollPane.getViewportBounds().getHeight() / scrollPane.getContent().getBoundsInLocal().getHeight();
double baseUnitIncrement = 0.15; var baseUnitIncrement = 0.15;
double unitIncrement = baseUnitIncrement * ratio * 1.25; var unitIncrement = baseUnitIncrement * ratio * 1.25;
getVerticalScrollBar().setUnitIncrement(unitIncrement); getVerticalScrollBar().setUnitIncrement(unitIncrement);
if (event.getDeltaX() < 0) { if (event.getDeltaX() < 0) {

View File

@ -12,12 +12,12 @@ public class FileSelectionBox extends AbstractFileSelectionBox {
@Override @Override
protected String validate(File file) { protected String validate(File file) {
if(isDisabled()) { if (isDisabled()) {
return null; return null;
} }
String msg = super.validate(file); String msg = super.validate(file);
if(msg != null) { if (msg != null) {
return msg; return msg;
} else if (!file.isFile()) { } else if (!file.isFile()) {
return "This is not a regular file"; return "This is not a regular file";

View File

@ -46,10 +46,8 @@ import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.event.Event; import javafx.event.Event;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Point2D; import javafx.geometry.Point2D;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button; import javafx.scene.control.Button;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent; import javafx.scene.input.MouseEvent;
@ -82,7 +80,7 @@ public class Popover extends Region implements EventHandler<Event>{
private final Region frameBorder = new Region(); private final Region frameBorder = new Region();
private final Button leftButton = new Button("Left"); private final Button leftButton = new Button("Left");
private final Button rightButton = new Button("Right"); private final Button rightButton = new Button("Right");
private final LinkedList<Page> pages = new LinkedList<Page>(); private final LinkedList<Page> pages = new LinkedList<>();
private final Pane pagesPane = new Pane(); private final Pane pagesPane = new Pane();
private final Rectangle pagesClipRect = new Rectangle(); private final Rectangle pagesClipRect = new Rectangle();
private final Pane titlesPane = new Pane(); private final Pane titlesPane = new Pane();
@ -128,11 +126,6 @@ public class Popover extends Region implements EventHandler<Event>{
t.consume(); t.consume();
} }
}; };
// popoverScrollHandler = new EventHandler<ScrollEvent>() {
// @Override public void handle(ScrollEvent t) {
// t.consume(); // consume all scroll events
// }
// };
} }
/** /**
@ -149,9 +142,9 @@ public class Popover extends Region implements EventHandler<Event>{
@Override protected double computeMinWidth(double height) { @Override protected double computeMinWidth(double height) {
Page page = pages.isEmpty() ? null : pages.getFirst(); Page page = pages.isEmpty() ? null : pages.getFirst();
if (page != null) { if (page != null) {
Node n = page.getPageNode(); var n = page.getPageNode();
if (n != null) { if (n != null) {
Insets insets = getInsets(); var insets = getInsets();
return insets.getLeft() + n.minWidth(-1) + insets.getRight(); return insets.getLeft() + n.minWidth(-1) + insets.getRight();
} }
} }
@ -159,16 +152,16 @@ public class Popover extends Region implements EventHandler<Event>{
} }
@Override protected double computeMinHeight(double width) { @Override protected double computeMinHeight(double width) {
Insets insets = getInsets(); var insets = getInsets();
return insets.getLeft() + 100 + insets.getRight(); return insets.getLeft() + 100 + insets.getRight();
} }
@Override protected double computePrefWidth(double height) { @Override protected double computePrefWidth(double height) {
Page page = pages.isEmpty() ? null : pages.getFirst(); Page page = pages.isEmpty() ? null : pages.getFirst();
if (page != null) { if (page != null) {
Node n = page.getPageNode(); var n = page.getPageNode();
if (n != null) { if (n != null) {
Insets insets = getInsets(); var insets = getInsets();
return insets.getLeft() + n.prefWidth(-1) + insets.getRight(); return insets.getLeft() + n.prefWidth(-1) + insets.getRight();
} }
} }
@ -180,9 +173,9 @@ public class Popover extends Region implements EventHandler<Event>{
double maxHeight = maxHeight(-1); double maxHeight = maxHeight(-1);
double prefHeight = popoverHeight.get(); double prefHeight = popoverHeight.get();
if (prefHeight == -1) { if (prefHeight == -1) {
Page page = pages.getFirst(); var page = pages.getFirst();
if (page != null) { if (page != null) {
Insets inset = getInsets(); var inset = getInsets();
if (width == -1) { if (width == -1) {
width = prefWidth(-1); width = prefWidth(-1);
} }
@ -208,7 +201,7 @@ public class Popover extends Region implements EventHandler<Event>{
} }
@Override protected double computeMaxHeight(double width) { @Override protected double computeMaxHeight(double width) {
Scene scene = getScene(); var scene = getScene();
if (scene != null) { if (scene != null) {
return scene.getHeight() - 100; return scene.getHeight() - 100;
} else { } else {
@ -220,14 +213,14 @@ public class Popover extends Region implements EventHandler<Event>{
if (maxPopupHeight == -1) { if (maxPopupHeight == -1) {
maxPopupHeight = (int)getScene().getHeight()-100; maxPopupHeight = (int)getScene().getHeight()-100;
} }
final Insets insets = getInsets(); final var insets = getInsets();
final int width = (int)getWidth(); final int width = (int)getWidth();
final int height = (int)getHeight(); final int height = (int)getHeight();
final int top = (int)insets.getTop() + 40; final int top = (int)insets.getTop() + 40;
final int right = (int)insets.getRight(); final int right = (int)insets.getRight();
final int bottom = (int)insets.getBottom(); final int bottom = (int)insets.getBottom();
final int left = (int)insets.getLeft(); final int left = (int)insets.getLeft();
final int offset = 18; final var offset = 18;
int pageWidth = width - left - right; int pageWidth = width - left - right;
int pageHeight = height - top - bottom; int pageHeight = height - top - bottom;
@ -238,19 +231,18 @@ public class Popover extends Region implements EventHandler<Event>{
pagesClipRect.setWidth(pageWidth); pagesClipRect.setWidth(pageWidth);
pagesClipRect.setHeight(pageHeight); pagesClipRect.setHeight(pageHeight);
int pageX = 0; var pageX = 0;
for (Node page : pagesPane.getChildren()) { for (Node page : pagesPane.getChildren()) {
page.resizeRelocate(pageX, 0, pageWidth, pageHeight); page.resizeRelocate(pageX, 0, pageWidth, pageHeight);
pageX += pageWidth + PAGE_GAP; pageX += pageWidth + PAGE_GAP;
} }
int buttonHeight = (int)(leftButton.prefHeight(-1)); int buttonHeight = Math.min(30, (int) (leftButton.prefHeight(-1)));
if (buttonHeight < 30) buttonHeight = 30; final int buttonTop = (int) ((top - buttonHeight) / 2d);
final int buttonTop = (int)((top-buttonHeight)/2d); final int leftButtonWidth = (int) snapSizeX(leftButton.prefWidth(-1));
final int leftButtonWidth = (int)snapSizeX(leftButton.prefWidth(-1)); leftButton.resizeRelocate(left, (double)buttonTop + offset, leftButtonWidth, buttonHeight);
leftButton.resizeRelocate(left, buttonTop + offset,leftButtonWidth,buttonHeight); final int rightButtonWidth = (int) snapSizeX(rightButton.prefWidth(-1));
final int rightButtonWidth = (int)snapSizeX(rightButton.prefWidth(-1)); rightButton.resizeRelocate(width - (double)right - rightButtonWidth, (double)buttonTop + offset, rightButtonWidth, buttonHeight);
rightButton.resizeRelocate(width-right-rightButtonWidth, buttonTop + offset,rightButtonWidth,buttonHeight);
if (title != null) { if (title != null) {
double tw = title.getWidth(); double tw = title.getWidth();
@ -275,16 +267,16 @@ public class Popover extends Region implements EventHandler<Event>{
} }
public final void popPage() { public final void popPage() {
Page oldPage = pages.pop(); var oldPage = pages.pop();
oldPage.handleHidden(); oldPage.handleHidden();
oldPage.setPopover(null); oldPage.setPopover(null);
Page page = pages.getFirst(); var page = pages.getFirst();
leftButton.setVisible(page.leftButtonText() != null); leftButton.setVisible(page.leftButtonText() != null);
leftButton.setText(page.leftButtonText()); leftButton.setText(page.leftButtonText());
rightButton.setVisible(page.rightButtonText() != null); rightButton.setVisible(page.rightButtonText() != null);
rightButton.setText(page.rightButtonText()); rightButton.setText(page.rightButtonText());
if (pages.size() > 0) { if (!pages.isEmpty()) {
final Insets insets = getInsets(); final var insets = getInsets();
final int width = (int)prefWidth(-1); final int width = (int)prefWidth(-1);
final int right = (int)insets.getRight(); final int right = (int)insets.getRight();
final int left = (int)insets.getLeft(); final int left = (int)insets.getLeft();
@ -308,10 +300,10 @@ public class Popover extends Region implements EventHandler<Event>{
} }
public final void pushPage(final Page page) { public final void pushPage(final Page page) {
final Node pageNode = page.getPageNode(); final var pageNode = page.getPageNode();
pageNode.setManaged(false); pageNode.setManaged(false);
pagesPane.getChildren().add(pageNode); pagesPane.getChildren().add(pageNode);
final Insets insets = getInsets(); final var insets = getInsets();
final int pageWidth = (int)(prefWidth(-1) - insets.getLeft() - insets.getRight()); final int pageWidth = (int)(prefWidth(-1) - insets.getLeft() - insets.getRight());
final int newPageX = (pageWidth + PAGE_GAP) * pages.size(); final int newPageX = (pageWidth + PAGE_GAP) * pages.size();
leftButton.setVisible(page.leftButtonText() != null); leftButton.setVisible(page.leftButtonText() != null);
@ -322,11 +314,11 @@ public class Popover extends Region implements EventHandler<Event>{
title = new Label(page.getPageTitle()); title = new Label(page.getPageTitle());
title.getStyleClass().add("popover-title"); title.getStyleClass().add("popover-title");
title.setTextAlignment(TextAlignment.CENTER); title.setTextAlignment(TextAlignment.CENTER);
title.setTranslateX(newPageX + (int) ((pageWidth - title.getLayoutBounds().getWidth()) / 2d)); title.setTranslateX(newPageX + (pageWidth - title.getLayoutBounds().getWidth()) / 2d);
titlesPane.getChildren().add(title); titlesPane.getChildren().add(title);
if (!pages.isEmpty() && isVisible()) { if (!pages.isEmpty() && isVisible()) {
final Timeline timeline = new Timeline( final var timeline = new Timeline(
new KeyFrame(Duration.millis(350), (ActionEvent t) -> { new KeyFrame(Duration.millis(350), (ActionEvent t) -> {
pagesPane.setCache(false); pagesPane.setCache(false);
resizePopoverToNewPage(pageNode); resizePopoverToNewPage(pageNode);
@ -344,7 +336,7 @@ public class Popover extends Region implements EventHandler<Event>{
} }
private void resizePopoverToNewPage(final Node newPageNode) { private void resizePopoverToNewPage(final Node newPageNode) {
final Insets insets = getInsets(); final var insets = getInsets();
final double width = prefWidth(-1); final double width = prefWidth(-1);
final double contentWidth = width - insets.getLeft() - insets.getRight(); final double contentWidth = width - insets.getLeft() - insets.getRight();
double h = newPageNode.prefHeight(contentWidth); double h = newPageNode.prefHeight(contentWidth);
@ -366,7 +358,6 @@ public class Popover extends Region implements EventHandler<Event>{
if (!isVisible() || fadeAnimation != null) { if (!isVisible() || fadeAnimation != null) {
this.onHideCallback = onHideCallback; this.onHideCallback = onHideCallback;
getScene().addEventFilter(MouseEvent.MOUSE_CLICKED, popoverHideHandler); getScene().addEventFilter(MouseEvent.MOUSE_CLICKED, popoverHideHandler);
// getScene().addEventFilter(ScrollEvent.ANY,popoverScrollHandler);
if (fadeAnimation != null) { if (fadeAnimation != null) {
fadeAnimation.stop(); fadeAnimation.stop();
@ -376,17 +367,15 @@ public class Popover extends Region implements EventHandler<Event>{
setVisible(true); setVisible(true);
} }
FadeTransition fade = new FadeTransition(Duration.seconds(.1), this); var fade = new FadeTransition(Duration.seconds(.1), this);
fade.setToValue(1.0); fade.setToValue(1.0);
fade.setOnFinished((ActionEvent event) -> { fade.setOnFinished((ActionEvent event) -> fadeAnimation = null);
fadeAnimation = null;
});
ScaleTransition scale = new ScaleTransition(Duration.seconds(.1), this); var scale = new ScaleTransition(Duration.seconds(.1), this);
scale.setToX(1); scale.setToX(1);
scale.setToY(1); scale.setToY(1);
ParallelTransition tx = new ParallelTransition(fade, scale); var tx = new ParallelTransition(fade, scale);
fadeAnimation = tx; fadeAnimation = tx;
tx.play(); tx.play();
} }
@ -395,26 +384,24 @@ public class Popover extends Region implements EventHandler<Event>{
public void hide(){ public void hide(){
if (isVisible() || fadeAnimation != null) { if (isVisible() || fadeAnimation != null) {
getScene().removeEventFilter(MouseEvent.MOUSE_CLICKED, popoverHideHandler); getScene().removeEventFilter(MouseEvent.MOUSE_CLICKED, popoverHideHandler);
// getScene().removeEventFilter(ScrollEvent.ANY,popoverScrollHandler);
if (fadeAnimation != null) { if (fadeAnimation != null) {
fadeAnimation.stop(); fadeAnimation.stop();
} }
FadeTransition fade = new FadeTransition(Duration.seconds(.1), this); var fade = new FadeTransition(Duration.seconds(.1), this);
fade.setToValue(0); fade.setToValue(0);
fade.setOnFinished((ActionEvent event) -> { fade.setOnFinished((ActionEvent event) -> {
fadeAnimation = null; fadeAnimation = null;
setVisible(false); setVisible(false);
//clearPages();
if (onHideCallback != null) onHideCallback.run(); if (onHideCallback != null) onHideCallback.run();
}); });
ScaleTransition scale = new ScaleTransition(Duration.seconds(.1), this); var scale = new ScaleTransition(Duration.seconds(.1), this);
scale.setToX(.8); scale.setToX(.8);
scale.setToY(.8); scale.setToY(.8);
ParallelTransition tx = new ParallelTransition(fade, scale); var tx = new ParallelTransition(fade, scale);
fadeAnimation = tx; fadeAnimation = tx;
tx.play(); tx.play();
} }

View File

@ -55,7 +55,7 @@ public class PopoverTreeList<T> extends ListView<T> implements Callback<ListView
return new TreeItemListCell(); return new TreeItemListCell();
} }
protected void itemClicked(T item) {} protected void itemClicked(T item) { /* nothing to do */ }
private class TreeItemListCell extends ListCell<T> implements EventHandler<MouseEvent> { private class TreeItemListCell extends ListCell<T> implements EventHandler<MouseEvent> {
private TreeItemListCell() { private TreeItemListCell() {

View File

@ -12,12 +12,12 @@ public class ProgramSelectionBox extends FileSelectionBox {
@Override @Override
protected String validate(File file) { protected String validate(File file) {
if(isDisabled()) { if (isDisabled()) {
return null; return null;
} }
String msg = super.validate(file); String msg = super.validate(file);
if(msg != null) { if (msg != null) {
return msg; return msg;
} else if (!file.canExecute()) { } else if (!file.canExecute()) {
return "This is not an executable application"; return "This is not an executable application";

View File

@ -34,4 +34,3 @@ public class RecordingIndicator extends StackPane {
icon.setImage(img); icon.setImage(img);
} }
} }

View File

@ -44,10 +44,10 @@ import javafx.scene.layout.Region;
* Search field with styling and a clear button * Search field with styling and a clear button
*/ */
public class SearchBox extends TextField implements ChangeListener<String>{ public class SearchBox extends TextField implements ChangeListener<String>{
private static final int PREF_HEIGHT = 26;
private final Button clearButton = new Button(); private final Button clearButton = new Button();
private final Region innerBackground = new Region(); private final Region innerBackground = new Region();
private final Region icon = new Region(); private final Region icon = new Region();
private final int prefHeight = 26;
public SearchBox() { public SearchBox() {
getStyleClass().addAll("search-box"); getStyleClass().addAll("search-box");
@ -55,7 +55,7 @@ public class SearchBox extends TextField implements ChangeListener<String>{
innerBackground.getStyleClass().setAll("search-box-inner"); innerBackground.getStyleClass().setAll("search-box-inner");
setPromptText("Search"); setPromptText("Search");
textProperty().addListener(this); textProperty().addListener(this);
setPrefHeight(prefHeight); setPrefHeight(PREF_HEIGHT);
clearButton.getStyleClass().setAll("search-clear-button"); clearButton.getStyleClass().setAll("search-clear-button");
clearButton.setCursor(Cursor.DEFAULT); clearButton.setCursor(Cursor.DEFAULT);
clearButton.setOnMouseClicked((MouseEvent t) -> { clearButton.setOnMouseClicked((MouseEvent t) -> {
@ -91,10 +91,10 @@ public class SearchBox extends TextField implements ChangeListener<String>{
innerBackground.resize(getWidth(), getHeight()); innerBackground.resize(getWidth(), getHeight());
icon.setLayoutX(0); icon.setLayoutX(0);
icon.setLayoutY(0); icon.setLayoutY(0);
icon.resize(35,prefHeight); icon.resize(35,PREF_HEIGHT);
clearButton.setLayoutX(getWidth() - prefHeight); clearButton.setLayoutX(getWidth() - PREF_HEIGHT);
clearButton.setLayoutY(0); clearButton.setLayoutY(0);
clearButton.resize(prefHeight, prefHeight); clearButton.resize(PREF_HEIGHT, PREF_HEIGHT);
} }
@Override public void changed(ObservableValue<? extends String> ov, String oldValue, String newValue) { @Override public void changed(ObservableValue<? extends String> ov, String oldValue, String newValue) {

View File

@ -1,6 +1,5 @@
package ctbrec.ui.controls.autocomplete; package ctbrec.ui.controls.autocomplete;
import java.util.Optional; import java.util.Optional;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
@ -36,18 +35,18 @@ public class AutoFillTextField extends TextField {
private void autocomplete(boolean fulltextSearch) { private void autocomplete(boolean fulltextSearch) {
String oldtext = getOldText(); String oldtext = getOldText();
if(oldtext.isEmpty()) { if (oldtext.isEmpty()) {
return; return;
} }
Optional<String> match = null; Optional<String> match;
if(fulltextSearch) { if (fulltextSearch) {
match = suggester.fulltext(oldtext); match = suggester.fulltext(oldtext);
} else { } else {
match = suggester.startsWith(oldtext); match = suggester.startsWith(oldtext);
} }
if(match.isPresent()) { if (match.isPresent()) {
setText(match.get()); setText(match.get());
int pos = oldtext.length(); int pos = oldtext.length();
positionCaret(pos); positionCaret(pos);
@ -56,7 +55,7 @@ public class AutoFillTextField extends TextField {
} }
private String getOldText() { private String getOldText() {
if(getSelection().getLength() > 0) { if (getSelection().getLength() > 0) {
return getText().substring(0, getSelection().getStart()); return getText().substring(0, getSelection().getStart());
} else { } else {
return getText(); return getText();

View File

@ -1,5 +0,0 @@
package ctbrec.ui.controls.autocomplete;
public class Suggestion {
}

View File

@ -35,8 +35,8 @@ public class RangeSliderBehavior<T extends Number> extends BehaviorBase<RangeSli
* The mouse position on track with 0.0 being beginning of track and 1.0 being the end * The mouse position on track with 0.0 being beginning of track and 1.0 being the end
*/ */
public void lowThumbDragged(double position) { public void lowThumbDragged(double position) {
T newPosition = getNewPosition(position); var newPosition = getNewPosition(position);
T high = getHigh(); var high = getHigh();
if (newPosition.doubleValue() >= high.doubleValue()) { if (newPosition.doubleValue() >= high.doubleValue()) {
newPosition = getLow(); newPosition = getLow();
} }
@ -48,8 +48,8 @@ public class RangeSliderBehavior<T extends Number> extends BehaviorBase<RangeSli
* The mouse position on track with 0.0 being beginning of track and 1.0 being the end * The mouse position on track with 0.0 being beginning of track and 1.0 being the end
*/ */
public void highThumbDragged(double position) { public void highThumbDragged(double position) {
T newPosition = getNewPosition(position); var newPosition = getNewPosition(position);
T low = getLow(); var low = getLow();
if (newPosition.doubleValue() <= low.doubleValue()) { if (newPosition.doubleValue() <= low.doubleValue()) {
newPosition = getHigh(); newPosition = getHigh();
} }
@ -57,9 +57,9 @@ public class RangeSliderBehavior<T extends Number> extends BehaviorBase<RangeSli
} }
public void moveClosestThumbTo(double positionPercentage) { public void moveClosestThumbTo(double positionPercentage) {
T newPosition = getNewPosition(positionPercentage); var newPosition = getNewPosition(positionPercentage);
T low = getLow(); var low = getLow();
T high = getHigh(); var high = getHigh();
double distToLow = Math.abs(low.doubleValue() - newPosition.doubleValue()); double distToLow = Math.abs(low.doubleValue() - newPosition.doubleValue());
double distToHigh = Math.abs(high.doubleValue() - newPosition.doubleValue()); double distToHigh = Math.abs(high.doubleValue() - newPosition.doubleValue());
if (distToLow < distToHigh) { if (distToLow < distToHigh) {

View File

@ -122,39 +122,39 @@ public class RangeSliderSkin extends SkinBase<RangeSlider<?>> {
thumbRange.high.resize(thumbWidth, thumbHeight); thumbRange.high.resize(thumbWidth, thumbHeight);
} }
// we are assuming the is common radius's for all corners on the track
double trackRadius = track.getBackground() == null ? 0
: !track.getBackground().getFills().isEmpty() ? track.getBackground().getFills().get(0).getRadii().getTopLeftHorizontalRadius() : 0;
double tickLineHeight = (showTickMarks) ? tickLine.prefHeight(-1) : 0; double radius = track.getBackground().getFills().isEmpty() ? 0 : track.getBackground().getFills().get(0).getRadii().getTopLeftHorizontalRadius();
double trackHeight = 5;// track.prefHeight(-1); double trackRadius = track.getBackground() == null ? 0 : radius;
double trackAreaHeight = Math.max(trackHeight, thumbHeight);
double totalHeightNeeded = trackAreaHeight + ((showTickMarks) ? TRACK_TO_TICK_GAP + tickLineHeight : 0);
double startY = y + ((h - totalHeightNeeded) / 2); // center slider in available height vertically
trackLength = w - thumbWidth; double tickLineHeight = (showTickMarks) ? tickLine.prefHeight(-1) : 0;
trackStart = x + (thumbWidth / 2); double trackHeight = 5;
double trackAreaHeight = Math.max(trackHeight, thumbHeight);
double totalHeightNeeded = trackAreaHeight + ((showTickMarks) ? TRACK_TO_TICK_GAP + tickLineHeight : 0);
double startY = y + ((h - totalHeightNeeded) / 2); // center slider in available height vertically
double trackTop = (int) (startY + ((trackAreaHeight - trackHeight) / 2)); trackLength = w - thumbWidth;
lowThumbPos = (int) (startY + ((trackAreaHeight - thumbHeight) / 2)); trackStart = x + (thumbWidth / 2);
// layout track double trackTop = (int) (startY + ((trackAreaHeight - trackHeight) / 2));
track.resizeRelocate(trackStart - trackRadius, trackTop, trackLength + trackRadius + trackRadius, trackHeight); lowThumbPos = (int) (startY + ((trackAreaHeight - thumbHeight) / 2));
positionThumbs(); // layout track
track.resizeRelocate(trackStart - trackRadius, trackTop, trackLength + trackRadius + trackRadius, trackHeight);
if (showTickMarks) { positionThumbs();
tickLine.setLayoutX(trackStart);
tickLine.setLayoutY(trackTop + trackHeight + TRACK_TO_TICK_GAP); if (showTickMarks) {
tickLine.resize(trackLength, tickLineHeight); tickLine.setLayoutX(trackStart);
tickLine.requestAxisLayout(); tickLine.setLayoutY(trackTop + trackHeight + TRACK_TO_TICK_GAP);
} else { tickLine.resize(trackLength, tickLineHeight);
if (tickLine != null) { tickLine.requestAxisLayout();
tickLine.resize(0, 0); } else {
tickLine.requestAxisLayout(); if (tickLine != null) {
} tickLine.resize(0, 0);
tickLine = null; tickLine.requestAxisLayout();
} }
tickLine = null;
}
} }
private void positionThumbs() { private void positionThumbs() {

View File

@ -23,13 +23,13 @@ public class PlaySound extends Action {
@Override @Override
public void accept(Event evt) { public void accept(Event evt) {
AudioClip clip = new AudioClip(url.toString()); var clip = new AudioClip(url.toString());
clip.play(); clip.play();
} }
@Override @Override
public void configure(ActionConfiguration config) throws Exception { public void configure(ActionConfiguration config) throws Exception {
File file = new File((String) config.getConfiguration().get("file")); var file = new File((String) config.getConfiguration().get("file"));
url = file.toURI().toURL(); url = file.toURI().toURL();
} }
} }

View File

@ -17,7 +17,7 @@ public class ShowNotification extends Action {
@Override @Override
public void accept(Event evt) { public void accept(Event evt) {
String header = evt.getType().toString(); var header = evt.getType().toString();
String msg; String msg;
switch(evt.getType()) { switch(evt.getType()) {
case MODEL_STATUS_CHANGED: case MODEL_STATUS_CHANGED:
@ -25,7 +25,7 @@ public class ShowNotification extends Action {
if (modelEvent.getOldState() == Model.State.UNKNOWN) { if (modelEvent.getOldState() == Model.State.UNKNOWN) {
return; return;
} }
Model m = modelEvent.getModel(); var m = modelEvent.getModel();
msg = m.getDisplayName() + " is now " + modelEvent.getNewState().toString(); msg = m.getDisplayName() + " is now " + modelEvent.getNewState().toString();
break; break;
case RECORDING_STATUS_CHANGED: case RECORDING_STATUS_CHANGED:
@ -41,5 +41,6 @@ public class ShowNotification extends Action {
@Override @Override
public void configure(ActionConfiguration config) throws Exception { public void configure(ActionConfiguration config) throws Exception {
// nothing to do here
} }
} }

View File

@ -22,7 +22,6 @@ import javafx.scene.control.ScrollPane;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response;
public class NewsTab extends Tab implements TabSelectionListener { public class NewsTab extends Tab implements TabSelectionListener {
private static final String ACCESS_TOKEN = "a2804d73a89951a22e0f8483a6fcec8943afd88b7ba17c459c095aa9e6f94fd0"; private static final String ACCESS_TOKEN = "a2804d73a89951a22e0f8483a6fcec8943afd88b7ba17c459c095aa9e6f94fd0";
@ -44,14 +43,14 @@ public class NewsTab extends Tab implements TabSelectionListener {
private void loadToots() { private void loadToots() {
try { try {
Request request = new Request.Builder() var request = new Request.Builder()
.url(URL) .url(URL)
.header("Authorization", "Bearer " + ACCESS_TOKEN) .header("Authorization", "Bearer " + ACCESS_TOKEN)
.header(USER_AGENT, "ctbrec " + CamrecApplication.getVersion().toString()) .header(USER_AGENT, "ctbrec " + CamrecApplication.getVersion().toString())
.build(); .build();
try (Response response = CamrecApplication.httpClient.execute(request)) { try (var response = CamrecApplication.httpClient.execute(request)) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
String body = response.body().string(); var body = response.body().string();
if (body.startsWith("[")) { if (body.startsWith("[")) {
onSuccess(body); onSuccess(body);
} else if (body.startsWith("{")) { } else if (body.startsWith("{")) {
@ -69,7 +68,7 @@ public class NewsTab extends Tab implements TabSelectionListener {
} }
private void onError(String body) throws IOException { private void onError(String body) throws IOException {
JSONObject json = new JSONObject(body); var json = new JSONObject(body);
if (json.has("error")) { if (json.has("error")) {
throw new IOException("Request not successful: " + json.getString("error")); throw new IOException("Request not successful: " + json.getString("error"));
} else { } else {
@ -78,14 +77,14 @@ public class NewsTab extends Tab implements TabSelectionListener {
} }
private void onSuccess(String body) throws IOException { private void onSuccess(String body) throws IOException {
Moshi moshi = new Moshi.Builder().build(); var moshi = new Moshi.Builder().build();
JsonAdapter<Status[]> statusListAdapter = moshi.adapter(Status[].class); JsonAdapter<Status[]> statusListAdapter = moshi.adapter(Status[].class);
Status[] statusArray = statusListAdapter.fromJson(body); Status[] statusArray = statusListAdapter.fromJson(body);
Platform.runLater(() -> { Platform.runLater(() -> {
layout.getChildren().clear(); layout.getChildren().clear();
for (Status status : statusArray) { for (Status status : statusArray) {
if (status.getInReplyToId() == null && !Objects.equals("direct", status.getVisibility())) { if (status.getInReplyToId() == null && !Objects.equals("direct", status.getVisibility())) {
StatusPane stp = new StatusPane(status); var stp = new StatusPane(status);
layout.getChildren().add(stp); layout.getChildren().add(stp);
VBox.setMargin(stp, new Insets(10)); VBox.setMargin(stp, new Insets(10));
} }

View File

@ -272,8 +272,8 @@ public class Status {
public ZonedDateTime getCreationTime() { public ZonedDateTime getCreationTime() {
String timestamp = getCreatedAt(); String timestamp = getCreatedAt();
Instant instant = Instant.parse(timestamp); var instant = Instant.parse(timestamp);
ZonedDateTime time = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault()); var time = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
return time; return time;
} }
} }

View File

@ -36,7 +36,7 @@ public class StatusPane extends StackPane {
ZonedDateTime createdAt = status.getCreationTime(); ZonedDateTime createdAt = status.getCreationTime();
String creationTime = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT, FormatStyle.SHORT).format(createdAt); String creationTime = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT, FormatStyle.SHORT).format(createdAt);
Label time = new Label(creationTime); var time = new Label(creationTime);
time.setStyle("-fx-background-color: -fx-base"); time.setStyle("-fx-background-color: -fx-base");
time.setOpacity(.7); time.setOpacity(.7);
time.setPadding(new Insets(3)); time.setPadding(new Insets(3));
@ -45,7 +45,7 @@ public class StatusPane extends StackPane {
getChildren().add(time); getChildren().add(time);
StackPane.setMargin(time, new Insets(5, 5, 5, 10)); StackPane.setMargin(time, new Insets(5, 5, 5, 10));
StackPane.setAlignment(time, Pos.BOTTOM_LEFT); StackPane.setAlignment(time, Pos.BOTTOM_LEFT);
Rectangle clip = new Rectangle(time.getWidth(), time.getHeight()); var clip = new Rectangle(time.getWidth(), time.getHeight());
clip.heightProperty().bind(time.heightProperty()); clip.heightProperty().bind(time.heightProperty());
clip.widthProperty().bind(time.widthProperty()); clip.widthProperty().bind(time.widthProperty());
clip.setArcHeight(5); clip.setArcHeight(5);
@ -53,7 +53,7 @@ public class StatusPane extends StackPane {
time.setClip(clip); time.setClip(clip);
reply = new Button("Reply"); reply = new Button("Reply");
reply.setOnAction((evt) -> DesktopIntegration.open(status.getUrl())); reply.setOnAction(evt -> DesktopIntegration.open(status.getUrl()));
getChildren().add(reply); getChildren().add(reply);
StackPane.setMargin(reply, new Insets(5, 5, 5, 5)); StackPane.setMargin(reply, new Insets(5, 5, 5, 5));
StackPane.setAlignment(reply, Pos.BOTTOM_RIGHT); StackPane.setAlignment(reply, Pos.BOTTOM_RIGHT);
@ -64,7 +64,7 @@ public class StatusPane extends StackPane {
ObservableList<Node> childrenUnmodifiable = content.getChildrenUnmodifiable(); ObservableList<Node> childrenUnmodifiable = content.getChildrenUnmodifiable();
for (Node node : childrenUnmodifiable) { for (Node node : childrenUnmodifiable) {
if (node instanceof ScrollPane) { if (node instanceof ScrollPane) {
ScrollPane scrollPane = (ScrollPane) node; var scrollPane = (ScrollPane) node;
Set<Node> nodes = scrollPane.lookupAll(".scroll-bar"); Set<Node> nodes = scrollPane.lookupAll(".scroll-bar");
for (final Node child : nodes) { for (final Node child : nodes) {
if (child instanceof ScrollBar) { if (child instanceof ScrollBar) {

View File

@ -47,13 +47,12 @@ public abstract class AbstractPostProcessingPaneFactory {
} }
class MapPreferencesStorage implements PreferencesStorage { class MapPreferencesStorage implements PreferencesStorage {
@Override @Override
public void save(Preferences preferences) throws IOException { public void save(Preferences preferences) throws IOException {
for (Property<?> property : properties) { for (Property<?> property : properties) {
String key = property.getName(); String key = property.getName();
Object value = preferences.getSetting(key).get().getProperty().getValue(); Object value = preferences.getSetting(key).get().getProperty().getValue();
LOG.debug("{}={}", key, value.toString()); LOG.debug("{}={}", key, value);
pp.getConfig().put(key, value.toString()); pp.getConfig().put(key, value.toString());
} }
} }
@ -64,7 +63,7 @@ public abstract class AbstractPostProcessingPaneFactory {
} }
@Override @Override
public Node createGui(Setting setting) throws Exception { public Node createGui(Setting setting) throws NoSuchFieldException, IllegalAccessException {
Property<?> prop = setting.getProperty(); Property<?> prop = setting.getProperty();
if (prop instanceof ExclusiveSelectionProperty) { if (prop instanceof ExclusiveSelectionProperty) {
return createRadioGroup(setting); return createRadioGroup(setting);
@ -86,109 +85,74 @@ public abstract class AbstractPostProcessingPaneFactory {
return new Label("Unsupported Type for key " + setting.getKey() + ": " + setting.getProperty()); return new Label("Unsupported Type for key " + setting.getKey() + ": " + setting.getProperty());
} }
} }
}
private Node createRadioGroup(Setting setting) { private Node createRadioGroup(Setting setting) {
ExclusiveSelectionProperty prop = (ExclusiveSelectionProperty) setting.getProperty(); ExclusiveSelectionProperty prop = (ExclusiveSelectionProperty) setting.getProperty();
ToggleGroup toggleGroup = new ToggleGroup(); var toggleGroup = new ToggleGroup();
RadioButton optionA = new RadioButton(prop.getOptionA()); var optionA = new RadioButton(prop.getOptionA());
optionA.setSelected(prop.getValue()); optionA.setSelected(prop.getValue());
optionA.setToggleGroup(toggleGroup); optionA.setToggleGroup(toggleGroup);
RadioButton optionB = new RadioButton(prop.getOptionB()); var optionB = new RadioButton(prop.getOptionB());
optionB.setSelected(!optionA.isSelected()); optionB.setSelected(!optionA.isSelected());
optionB.setToggleGroup(toggleGroup); optionB.setToggleGroup(toggleGroup);
optionA.selectedProperty().bindBidirectional(prop); optionA.selectedProperty().bindBidirectional(prop);
HBox row = new HBox(); var row = new HBox();
row.getChildren().addAll(optionA, optionB); row.getChildren().addAll(optionA, optionB);
HBox.setMargin(optionA, new Insets(5)); HBox.setMargin(optionA, new Insets(5));
HBox.setMargin(optionB, new Insets(5)); HBox.setMargin(optionB, new Insets(5));
return row; return row;
} }
private Node createFileSelector(Setting setting) { private Node createFileSelector(Setting setting) {
ProgramSelectionBox programSelector = new ProgramSelectionBox(""); var programSelector = new ProgramSelectionBox("");
// programSelector.fileProperty().addListener((obs, o, n) -> saveValue(() -> { StringProperty property = (StringProperty) setting.getProperty();
// String path = n; programSelector.fileProperty().bindBidirectional(property);
// Field field = Settings.class.getField(setting.getKey()); return programSelector;
// String oldValue = (String) field.get(settings); }
// if (!Objects.equals(path, oldValue)) {
// field.set(settings, path);
// config.save();
// }
// }));
StringProperty property = (StringProperty) setting.getProperty();
programSelector.fileProperty().bindBidirectional(property);
return programSelector;
}
private Node createDirectorySelector(Setting setting) { private Node createDirectorySelector(Setting setting) {
DirectorySelectionBox directorySelector = new DirectorySelectionBox(""); var directorySelector = new DirectorySelectionBox("");
directorySelector.prefWidth(400); directorySelector.prefWidth(400);
// directorySelector.fileProperty().addListener((obs, o, n) -> saveValue(() -> { StringProperty property = (StringProperty) setting.getProperty();
// String path = n; directorySelector.fileProperty().bindBidirectional(property);
// Field field = Settings.class.getField(setting.getKey()); return directorySelector;
// String oldValue = (String) field.get(settings); }
// if (!Objects.equals(path, oldValue)) {
// field.set(settings, path);
// config.save();
// }
// }));
StringProperty property = (StringProperty) setting.getProperty();
directorySelector.fileProperty().bindBidirectional(property);
return directorySelector;
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private Node createStringProperty(Setting setting) { private Node createStringProperty(Setting setting) {
TextField ctrl = new TextField(); var ctrl = new TextField();
ctrl.textProperty().bindBidirectional(setting.getProperty()); ctrl.textProperty().bindBidirectional(setting.getProperty());
return ctrl; return ctrl;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private Node createIntegerProperty(Setting setting) { private Node createIntegerProperty(Setting setting) {
TextField ctrl = new TextField(); var ctrl = new TextField();
Property<Number> prop = setting.getProperty(); Property<Number> prop = setting.getProperty();
ctrl.textProperty().bindBidirectional(prop, new NumberStringConverter()); ctrl.textProperty().bindBidirectional(prop, new NumberStringConverter());
return ctrl; return ctrl;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private Node createLongProperty(Setting setting) { private Node createLongProperty(Setting setting) {
TextField ctrl = new TextField(); var ctrl = new TextField();
Property<Number> prop = setting.getProperty(); Property<Number> prop = setting.getProperty();
ctrl.textProperty().bindBidirectional(prop, new NumberStringConverter()); ctrl.textProperty().bindBidirectional(prop, new NumberStringConverter());
return ctrl; return ctrl;
} }
private Node createBooleanProperty(Setting setting) { private Node createBooleanProperty(Setting setting) {
CheckBox ctrl = new CheckBox(); var ctrl = new CheckBox();
BooleanProperty prop = (BooleanProperty) setting.getProperty(); BooleanProperty prop = (BooleanProperty) setting.getProperty();
ctrl.selectedProperty().bindBidirectional(prop); ctrl.selectedProperty().bindBidirectional(prop);
return ctrl; return ctrl;
} }
@SuppressWarnings({ "rawtypes", "unchecked" }) @SuppressWarnings({ "rawtypes", "unchecked" })
private Node createComboBox(Setting setting) throws NoSuchFieldException, IllegalAccessException { private Node createComboBox(Setting setting) {
ListProperty<?> listProp = (ListProperty<?>) setting.getProperty(); ListProperty<?> listProp = (ListProperty<?>) setting.getProperty();
ComboBox<Object> comboBox = new ComboBox(listProp); ComboBox<Object> comboBox = new ComboBox(listProp);
// Field field = Settings.class.getField(setting.getKey()); return comboBox;
// Object value = field.get(Config.getInstance().getSettings()); }
// if (StringUtil.isNotBlank(value.toString())) {
// if (setting.getConverter() != null) {
// comboBox.getSelectionModel().select(setting.getConverter().convertTo(value));
// } else {
// comboBox.getSelectionModel().select(value);
// }
// }
// comboBox.valueProperty().addListener((obs, oldV, newV) -> saveValue(() -> {
// if (setting.getConverter() != null) {
// field.set(settings, setting.getConverter().convertFrom(newV));
// } else {
// field.set(settings, newV);
// }
// config.save();
// }));
return comboBox;
} }
} }

View File

@ -94,24 +94,24 @@ public class ActionSettingsPanel extends GridPane {
setVgap(10); setVgap(10);
setPadding(new Insets(20, 10, 10, 10)); setPadding(new Insets(20, 10, 10, 10));
Label headline = new Label("Events & Actions"); var headline = new Label("Events & Actions");
headline.getStyleClass().add("settings-group-label"); headline.getStyleClass().add("settings-group-label");
add(headline, 0, 0); add(headline, 0, 0);
actionTable = createActionTable(); actionTable = createActionTable();
ScrollPane scrollPane = new ScrollPane(actionTable); var scrollPane = new ScrollPane(actionTable);
scrollPane.setFitToHeight(true); scrollPane.setFitToHeight(true);
scrollPane.setFitToWidth(true); scrollPane.setFitToWidth(true);
scrollPane.setStyle("-fx-background-color: -fx-background"); scrollPane.setStyle("-fx-background-color: -fx-background");
add(scrollPane, 0, 1); add(scrollPane, 0, 1);
GridPane.setHgrow(scrollPane, Priority.ALWAYS); GridPane.setHgrow(scrollPane, Priority.ALWAYS);
Button add = new Button("Add"); var add = new Button("Add");
add.setOnAction(this::add); add.setOnAction(this::add);
Button delete = new Button("Delete"); var delete = new Button("Delete");
delete.setOnAction(this::delete); delete.setOnAction(this::delete);
delete.setDisable(true); delete.setDisable(true);
HBox buttons = new HBox(5, add, delete); var buttons = new HBox(5, add, delete);
buttons.setStyle("-fx-background-color: -fx-background"); // workaround so that the buttons don't shrink buttons.setStyle("-fx-background-color: -fx-background"); // workaround so that the buttons don't shrink
add(buttons, 0, 2); add(buttons, 0, 2);
@ -119,15 +119,15 @@ public class ActionSettingsPanel extends GridPane {
} }
private void add(ActionEvent evt) { private void add(ActionEvent evt) {
Pane actionPane = createActionPane(); var actionPane = createActionPane();
Stage dialog = new Stage(); var dialog = new Stage();
dialog.initModality(Modality.APPLICATION_MODAL); dialog.initModality(Modality.APPLICATION_MODAL);
dialog.initOwner(getScene().getWindow()); dialog.initOwner(getScene().getWindow());
dialog.setTitle("New Action"); dialog.setTitle("New Action");
InputStream icon = getClass().getResourceAsStream("/icon.png"); InputStream icon = getClass().getResourceAsStream("/icon.png");
dialog.getIcons().add(new Image(icon)); dialog.getIcons().add(new Image(icon));
Wizard root = new Wizard(dialog, this::validateSettings, actionPane); var root = new Wizard(dialog, this::validateSettings, actionPane);
Scene scene = new Scene(root, 800, 540); var scene = new Scene(root, 800, 540);
scene.getStylesheets().addAll(getScene().getStylesheets()); scene.getStylesheets().addAll(getScene().getStylesheets());
dialog.setScene(scene); dialog.setScene(scene);
centerOnParent(dialog); centerOnParent(dialog);
@ -138,58 +138,58 @@ public class ActionSettingsPanel extends GridPane {
} }
private void createEventHandler() { private void createEventHandler() {
EventHandlerConfiguration config = new EventHandlerConfiguration(); var config = new EventHandlerConfiguration();
config.setName(name.getText()); config.setName(name.getText());
config.setEvent(event.getValue()); config.setEvent(event.getValue());
if(event.getValue() == Event.Type.MODEL_STATUS_CHANGED) { if(event.getValue() == Event.Type.MODEL_STATUS_CHANGED) {
PredicateConfiguration pc = new PredicateConfiguration(); var pc = new PredicateConfiguration();
pc.setType(ModelStatePredicate.class.getName()); pc.setType(ModelStatePredicate.class.getName());
pc.getConfiguration().put("state", modelState.getValue().name()); pc.getConfiguration().put("state", modelState.getValue().name());
pc.setName("state = " + modelState.getValue().toString()); pc.setName("state = " + modelState.getValue().toString());
config.getPredicates().add(pc); config.getPredicates().add(pc);
} else if(event.getValue() == Event.Type.RECORDING_STATUS_CHANGED) { } else if(event.getValue() == Event.Type.RECORDING_STATUS_CHANGED) {
PredicateConfiguration pc = new PredicateConfiguration(); var pc = new PredicateConfiguration();
pc.setType(RecordingStatePredicate.class.getName()); pc.setType(RecordingStatePredicate.class.getName());
pc.getConfiguration().put("state", recordingState.getValue().name()); pc.getConfiguration().put("state", recordingState.getValue().name());
pc.setName("state = " + recordingState.getValue().toString()); pc.setName("state = " + recordingState.getValue().toString());
config.getPredicates().add(pc); config.getPredicates().add(pc);
} else if(event.getValue() == Event.Type.NO_SPACE_LEFT) { } else if(event.getValue() == Event.Type.NO_SPACE_LEFT) {
PredicateConfiguration pc = new PredicateConfiguration(); var pc = new PredicateConfiguration();
pc.setType(MatchAllPredicate.class.getName()); pc.setType(MatchAllPredicate.class.getName());
pc.setName("no space left"); pc.setName("no space left");
config.getPredicates().add(pc); config.getPredicates().add(pc);
} }
if(!modelSelectionPane.isAllSelected()) { if(!modelSelectionPane.isAllSelected()) {
PredicateConfiguration pc = new PredicateConfiguration(); var pc = new PredicateConfiguration();
pc.setType(ModelPredicate.class.getName()); pc.setType(ModelPredicate.class.getName());
pc.setModels(modelSelectionPane.getSelectedItems()); pc.setModels(modelSelectionPane.getSelectedItems());
pc.setName("model is one of:" + modelSelectionPane.getSelectedItems()); pc.setName("model is one of:" + modelSelectionPane.getSelectedItems());
config.getPredicates().add(pc); config.getPredicates().add(pc);
} }
if(showNotification.isSelected()) { if(showNotification.isSelected()) {
ActionConfiguration ac = new ActionConfiguration(); var ac = new ActionConfiguration();
ac.setType(ShowNotification.class.getName()); ac.setType(ShowNotification.class.getName());
ac.setName("show notification"); ac.setName("show notification");
config.getActions().add(ac); config.getActions().add(ac);
} }
if(playSound.isSelected()) { if(playSound.isSelected()) {
ActionConfiguration ac = new ActionConfiguration(); var ac = new ActionConfiguration();
ac.setType(PlaySound.class.getName()); ac.setType(PlaySound.class.getName());
File file = new File(sound.fileProperty().get()); var file = new File(sound.fileProperty().get());
ac.getConfiguration().put("file", file.getAbsolutePath()); ac.getConfiguration().put("file", file.getAbsolutePath());
ac.setName("play " + file.getName()); ac.setName("play " + file.getName());
config.getActions().add(ac); config.getActions().add(ac);
} }
if(executeProgram.isSelected()) { if(executeProgram.isSelected()) {
ActionConfiguration ac = new ActionConfiguration(); var ac = new ActionConfiguration();
ac.setType(ExecuteProgram.class.getName()); ac.setType(ExecuteProgram.class.getName());
File file = new File(program.fileProperty().get()); var file = new File(program.fileProperty().get());
ac.getConfiguration().put("file", file.getAbsolutePath()); ac.getConfiguration().put("file", file.getAbsolutePath());
ac.setName("execute " + file.getName()); ac.setName("execute " + file.getName());
config.getActions().add(ac); config.getActions().add(ac);
} }
EventHandler handler = new EventHandler(config); var handler = new EventHandler(config);
EventBusHolder.register(handler); EventBusHolder.register(handler);
Config.getInstance().getSettings().eventHandlers.add(config); Config.getInstance().getSettings().eventHandlers.add(config);
actionTable.getItems().add(config); actionTable.getItems().add(config);
@ -229,7 +229,7 @@ public class ActionSettingsPanel extends GridPane {
modelState.prefWidthProperty().bind(event.widthProperty()); modelState.prefWidthProperty().bind(event.widthProperty());
name.prefWidthProperty().bind(event.widthProperty()); name.prefWidthProperty().bind(event.widthProperty());
int row = 0; var row = 0;
layout.add(new Label("Name"), 0, row); layout.add(new Label("Name"), 0, row);
layout.add(name, 1, row++); layout.add(name, 1, row++);
@ -243,7 +243,7 @@ public class ActionSettingsPanel extends GridPane {
layout.add(event, 1, row++); layout.add(event, 1, row++);
event.getSelectionModel().selectedItemProperty().addListener((obs, oldV, newV) -> { event.getSelectionModel().selectedItemProperty().addListener((obs, oldV, newV) -> {
boolean modelRelatedStuffDisabled = false; var modelRelatedStuffDisabled = false;
if(newV == Event.Type.NO_SPACE_LEFT) { if(newV == Event.Type.NO_SPACE_LEFT) {
modelRelatedStuffDisabled = true; modelRelatedStuffDisabled = true;
modelSelectionPane.selectAll(); modelSelectionPane.selectAll();
@ -265,7 +265,7 @@ public class ActionSettingsPanel extends GridPane {
layout.add(createSeparator(), 0, row++); layout.add(createSeparator(), 0, row++);
Label l = new Label("Models"); var l = new Label("Models");
layout.add(l, 0, row); layout.add(l, 0, row);
modelSelectionPane = new ListSelectionPane<>(recorder.getModels(), Collections.emptyList()); modelSelectionPane = new ListSelectionPane<>(recorder.getModels(), Collections.emptyList());
layout.add(modelSelectionPane, 1, row++); layout.add(modelSelectionPane, 1, row++);
@ -278,8 +278,8 @@ public class ActionSettingsPanel extends GridPane {
layout.add(showNotification, 0, row); layout.add(showNotification, 0, row);
layout.add(testNotification, 1, row++); layout.add(testNotification, 1, row++);
testNotification.setOnAction(evt -> { testNotification.setOnAction(evt -> {
DateTimeFormatter format = DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM); var format = DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM);
ZonedDateTime time = ZonedDateTime.now(); var time = ZonedDateTime.now();
DesktopIntegration.notification(CamrecApplication.title, "Test Notification", "Oi, what's up! " + format.format(time)); DesktopIntegration.notification(CamrecApplication.title, "Test Notification", "Oi, what's up! " + format.format(time));
}); });
testNotification.disableProperty().bind(showNotification.selectedProperty().not()); testNotification.disableProperty().bind(showNotification.selectedProperty().not());
@ -306,12 +306,12 @@ public class ActionSettingsPanel extends GridPane {
} }
private Node createSeparator() { private Node createSeparator() {
Separator divider = new Separator(Orientation.HORIZONTAL); var divider = new Separator(Orientation.HORIZONTAL);
GridPane.setHgrow(divider, Priority.ALWAYS); GridPane.setHgrow(divider, Priority.ALWAYS);
GridPane.setFillWidth(divider, true); GridPane.setFillWidth(divider, true);
GridPane.setColumnSpan(divider, 2); GridPane.setColumnSpan(divider, 2);
int tb = 20; var tb = 20;
int lr = 0; var lr = 0;
GridPane.setMargin(divider, new Insets(tb, lr, tb, lr)); GridPane.setMargin(divider, new Insets(tb, lr, tb, lr));
return divider; return divider;
} }

View File

@ -61,7 +61,7 @@ public class ColorSettingsPane extends HBox {
} }
private String toWeb(Color value) { private String toWeb(Color value) {
StringBuilder sb = new StringBuilder("#"); var sb = new StringBuilder("#");
sb.append(toHex((int) (value.getRed() * 255))); sb.append(toHex((int) (value.getRed() * 255)));
sb.append(toHex((int) (value.getGreen() * 255))); sb.append(toHex((int) (value.getGreen() * 255)));
sb.append(toHex((int) (value.getBlue() * 255))); sb.append(toHex((int) (value.getBlue() * 255)));
@ -72,7 +72,7 @@ public class ColorSettingsPane extends HBox {
} }
private CharSequence toHex(int v) { private CharSequence toHex(int v) {
StringBuilder sb = new StringBuilder(); var sb = new StringBuilder();
if(v < 16) { if(v < 16) {
sb.append('0'); sb.append('0');
} }

View File

@ -18,13 +18,13 @@ public class CreateContactSheetPaneFactory extends AbstractPostProcessingPaneFac
@Override @Override
public Preferences doCreatePostProcessorPane(PostProcessor pp) { public Preferences doCreatePostProcessorPane(PostProcessor pp) {
SimpleStringProperty totalSize = new SimpleStringProperty(null, TOTAL_SIZE, pp.getConfig().getOrDefault(TOTAL_SIZE, "1920")); var totalSize = new SimpleStringProperty(null, TOTAL_SIZE, pp.getConfig().getOrDefault(TOTAL_SIZE, "1920"));
SimpleStringProperty padding = new SimpleStringProperty(null, PADDING, pp.getConfig().getOrDefault(PADDING, "4")); var padding = new SimpleStringProperty(null, PADDING, pp.getConfig().getOrDefault(PADDING, "4"));
SimpleStringProperty cols = new SimpleStringProperty(null, COLS, pp.getConfig().getOrDefault(COLS, "8")); var cols = new SimpleStringProperty(null, COLS, pp.getConfig().getOrDefault(COLS, "8"));
SimpleStringProperty rows = new SimpleStringProperty(null, ROWS, pp.getConfig().getOrDefault(ROWS, "7")); var rows = new SimpleStringProperty(null, ROWS, pp.getConfig().getOrDefault(ROWS, "7"));
SimpleStringProperty filename = new SimpleStringProperty(null, FILENAME, pp.getConfig().getOrDefault(FILENAME, "contactsheet.jpg")); var filename = new SimpleStringProperty(null, FILENAME, pp.getConfig().getOrDefault(FILENAME, "contactsheet.jpg"));
background = new SimpleStringProperty(null, BACKGROUND, pp.getConfig().getOrDefault(BACKGROUND, "0x333333")); background = new SimpleStringProperty(null, BACKGROUND, pp.getConfig().getOrDefault(BACKGROUND, "0x333333"));
SimpleBooleanProperty burnTimestamp = new SimpleBooleanProperty(null, BURN_IN_TIMESTAMP, var burnTimestamp = new SimpleBooleanProperty(null, BURN_IN_TIMESTAMP,
Boolean.valueOf(pp.getConfig().getOrDefault(BURN_IN_TIMESTAMP, TRUE.toString()))); Boolean.valueOf(pp.getConfig().getOrDefault(BURN_IN_TIMESTAMP, TRUE.toString())));
properties.add(totalSize); properties.add(totalSize);
properties.add(padding); properties.add(padding);
@ -34,8 +34,8 @@ public class CreateContactSheetPaneFactory extends AbstractPostProcessingPaneFac
properties.add(background); properties.add(background);
properties.add(burnTimestamp); properties.add(burnTimestamp);
Setting backgroundSetting = Setting.of("", background, "Hexadecimal value of the background color for the space between the thumbnails"); var backgroundSetting = Setting.of("", background, "Hexadecimal value of the background color for the space between the thumbnails");
Preferences prefs = Preferences.of(new MapPreferencesStorage(), var prefs = Preferences.of(new MapPreferencesStorage(),
Category.of(pp.getName(), Category.of(pp.getName(),
Setting.of("Total Width", totalSize, "Total width of the generated contact sheet"), Setting.of("Total Width", totalSize, "Total width of the generated contact sheet"),
Setting.of("Padding", padding, "Padding between the thumbnails"), Setting.of("Padding", padding, "Padding between the thumbnails"),
@ -59,8 +59,8 @@ public class CreateContactSheetPaneFactory extends AbstractPostProcessingPaneFac
} }
private ColorPicker createColorPicker(String hexColor) { private ColorPicker createColorPicker(String hexColor) {
Color preselection = Color.web(hexColor); var preselection = Color.web(hexColor);
ColorPicker colorPicker = new ColorPicker(preselection); var colorPicker = new ColorPicker(preselection);
colorPicker.setOnAction(e -> background.set(colorPicker.getValue().toString())); colorPicker.setOnAction(e -> background.set(colorPicker.getValue().toString()));
return colorPicker; return colorPicker;
} }

View File

@ -1,7 +1,6 @@
package ctbrec.ui.settings; package ctbrec.ui.settings;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Field;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
@ -71,55 +70,55 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
} }
@Override @Override
public Node createGui(Setting setting) throws Exception { public Node createGui(Setting setting) throws NoSuchFieldException, IllegalAccessException {
config.disableSaving(); config.disableSaving();
try { try {
Property<?> prop = setting.getProperty(); Property<?> prop = setting.getProperty();
if (prop instanceof ExclusiveSelectionProperty) { if (prop instanceof ExclusiveSelectionProperty) {
return createRadioGroup(setting); return createRadioGroup(setting);
} else if (prop instanceof SimpleRangeProperty) { } else if (prop instanceof SimpleRangeProperty) {
return createRangeSlider(setting); return createRangeSlider(setting);
} else if (prop instanceof SimpleDirectoryProperty) { } else if (prop instanceof SimpleDirectoryProperty) {
return createDirectorySelector(setting); return createDirectorySelector(setting);
} else if (prop instanceof SimpleFileProperty) { } else if (prop instanceof SimpleFileProperty) {
return createFileSelector(setting); return createFileSelector(setting);
} else if (prop instanceof IntegerProperty) { } else if (prop instanceof IntegerProperty) {
return createIntegerProperty(setting); return createIntegerProperty(setting);
} else if (prop instanceof LongProperty) { } else if (prop instanceof LongProperty) {
return createLongProperty(setting); return createLongProperty(setting);
} else if (prop instanceof BooleanProperty) { } else if (prop instanceof BooleanProperty) {
return createBooleanProperty(setting); return createBooleanProperty(setting);
} else if (prop instanceof ListProperty) { } else if (prop instanceof ListProperty) {
return createComboBox(setting); return createComboBox(setting);
} else if (prop instanceof StringProperty) { } else if (prop instanceof StringProperty) {
return createStringProperty(setting); return createStringProperty(setting);
} else { } else {
return new Label("Unsupported Type for key " + setting.getKey() + ": " + setting.getProperty()); return new Label("Unsupported Type for key " + setting.getKey() + ": " + setting.getProperty());
} }
} finally { } finally {
config.enableSaving(); config.enableSaving();
} }
} }
private Node createRadioGroup(Setting setting) { private Node createRadioGroup(Setting setting) {
ExclusiveSelectionProperty prop = (ExclusiveSelectionProperty) setting.getProperty(); ExclusiveSelectionProperty prop = (ExclusiveSelectionProperty) setting.getProperty();
ToggleGroup toggleGroup = new ToggleGroup(); var toggleGroup = new ToggleGroup();
RadioButton optionA = new RadioButton(prop.getOptionA()); var optionA = new RadioButton(prop.getOptionA());
optionA.setSelected(prop.getValue()); optionA.setSelected(prop.getValue());
optionA.setToggleGroup(toggleGroup); optionA.setToggleGroup(toggleGroup);
RadioButton optionB = new RadioButton(prop.getOptionB()); var optionB = new RadioButton(prop.getOptionB());
optionB.setSelected(!optionA.isSelected()); optionB.setSelected(!optionA.isSelected());
optionB.setToggleGroup(toggleGroup); optionB.setToggleGroup(toggleGroup);
optionA.selectedProperty().bindBidirectional(prop); optionA.selectedProperty().bindBidirectional(prop);
prop.addListener((obs, oldV, newV) -> saveValue(() -> { prop.addListener((obs, oldV, newV) -> saveValue(() -> {
Field field = Settings.class.getField(setting.getKey()); var field = Settings.class.getField(setting.getKey());
field.set(settings, newV); field.set(settings, newV); // NOSONAR
if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) { if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) {
runRestartRequiredCallback(); runRestartRequiredCallback();
} }
config.save(); config.save();
})); }));
HBox row = new HBox(); var row = new HBox();
row.getChildren().addAll(optionA, optionB); row.getChildren().addAll(optionA, optionB);
HBox.setMargin(optionA, new Insets(5)); HBox.setMargin(optionA, new Insets(5));
HBox.setMargin(optionB, new Insets(5)); HBox.setMargin(optionB, new Insets(5));
@ -151,22 +150,22 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
resolutionRange.setHigh(highValue >= 0 ? highValue : values.get(values.size() - 1)); resolutionRange.setHigh(highValue >= 0 ? highValue : values.get(values.size() - 1));
resolutionRange.getLow().addListener((obs, o, n) -> saveValue(() -> { resolutionRange.getLow().addListener((obs, o, n) -> saveValue(() -> {
int newV = labels.get(n.intValue()); int newV = labels.get(n.intValue());
Field field = Settings.class.getField(rangeProperty.getLowKey()); var field = Settings.class.getField(rangeProperty.getLowKey());
field.set(settings, newV); field.set(settings, newV); // NOSONAR
config.save(); config.save();
})); }));
resolutionRange.getHigh().addListener((obs, o, n) -> saveValue(() -> { resolutionRange.getHigh().addListener((obs, o, n) -> saveValue(() -> {
int newV = labels.get(n.intValue()); int newV = labels.get(n.intValue());
Field field = Settings.class.getField(rangeProperty.getHighKey()); var field = Settings.class.getField(rangeProperty.getHighKey());
field.set(settings, newV); field.set(settings, newV); // NOSONAR
config.save(); config.save();
})); }));
return resolutionRange; return resolutionRange;
} }
private int getRangeSliderValue(List<Integer> values, List<Integer> labels, int value) { private int getRangeSliderValue(List<Integer> values, List<Integer> labels, int value) {
for (int i = 0; i < labels.size(); i++) { for (var i = 0; i < labels.size(); i++) {
int label = labels.get(i).intValue(); var label = labels.get(i).intValue();
if (label == value) { if (label == value) {
return values.get(i); return values.get(i);
} }
@ -175,13 +174,13 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
} }
private Node createFileSelector(Setting setting) { private Node createFileSelector(Setting setting) {
ProgramSelectionBox programSelector = new ProgramSelectionBox(""); var programSelector = new ProgramSelectionBox("");
programSelector.fileProperty().addListener((obs, o, n) -> saveValue(() -> { programSelector.fileProperty().addListener((obs, o, n) -> saveValue(() -> {
String path = n; String path = n;
Field field = Settings.class.getField(setting.getKey()); var field = Settings.class.getField(setting.getKey());
String oldValue = (String) field.get(settings); String oldValue = (String) field.get(settings);
if (!Objects.equals(path, oldValue)) { if (!Objects.equals(path, oldValue)) {
field.set(settings, path); field.set(settings, path); // NOSONAR
if (setting.doesNeedRestart()) { if (setting.doesNeedRestart()) {
runRestartRequiredCallback(); runRestartRequiredCallback();
} }
@ -194,14 +193,14 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
} }
private Node createDirectorySelector(Setting setting) { private Node createDirectorySelector(Setting setting) {
DirectorySelectionBox directorySelector = new DirectorySelectionBox(""); var directorySelector = new DirectorySelectionBox("");
directorySelector.prefWidth(400); directorySelector.prefWidth(400);
directorySelector.fileProperty().addListener((obs, o, n) -> saveValue(() -> { directorySelector.fileProperty().addListener((obs, o, n) -> saveValue(() -> {
String path = n; String path = n;
Field field = Settings.class.getField(setting.getKey()); var field = Settings.class.getField(setting.getKey());
String oldValue = (String) field.get(settings); String oldValue = (String) field.get(settings);
if (!Objects.equals(path, oldValue)) { if (!Objects.equals(path, oldValue)) {
field.set(settings, path); field.set(settings, path); // NOSONAR
if (setting.doesNeedRestart()) { if (setting.doesNeedRestart()) {
runRestartRequiredCallback(); runRestartRequiredCallback();
} }
@ -214,10 +213,10 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
} }
private Node createStringProperty(Setting setting) { private Node createStringProperty(Setting setting) {
TextField ctrl = new TextField(); var ctrl = new TextField();
ctrl.textProperty().addListener((obs, oldV, newV) -> saveValue(() -> { ctrl.textProperty().addListener((obs, oldV, newV) -> saveValue(() -> {
Field field = Settings.class.getField(setting.getKey()); var field = Settings.class.getField(setting.getKey());
field.set(settings, newV); field.set(settings, newV); // NOSONAR
if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) { if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) {
runRestartRequiredCallback(); runRestartRequiredCallback();
} }
@ -230,14 +229,14 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private Node createIntegerProperty(Setting setting) { private Node createIntegerProperty(Setting setting) {
TextField ctrl = new TextField(); var ctrl = new TextField();
ctrl.textProperty().addListener((obs, oldV, newV) -> saveValue(() -> { ctrl.textProperty().addListener((obs, oldV, newV) -> saveValue(() -> {
if (!newV.matches("\\d*")) { if (!newV.matches("\\d*")) {
ctrl.setText(newV.replaceAll(PATTERN_NOT_A_DIGIT, "")); ctrl.setText(newV.replaceAll(PATTERN_NOT_A_DIGIT, ""));
} }
if (!ctrl.getText().isEmpty()) { if (!ctrl.getText().isEmpty()) {
Field field = Settings.class.getField(setting.getKey()); var field = Settings.class.getField(setting.getKey());
field.set(settings, Integer.parseInt(ctrl.getText())); field.set(settings, Integer.parseInt(ctrl.getText())); // NOSONAR
if (setting.doesNeedRestart() && !Objects.equals(oldV, newV) && prefs != null) { if (setting.doesNeedRestart() && !Objects.equals(oldV, newV) && prefs != null) {
runRestartRequiredCallback(); runRestartRequiredCallback();
} }
@ -251,18 +250,18 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private Node createLongProperty(Setting setting) { private Node createLongProperty(Setting setting) {
TextField ctrl = new TextField(); var ctrl = new TextField();
ctrl.textProperty().addListener((obs, oldV, newV) -> saveValue(() -> { ctrl.textProperty().addListener((obs, oldV, newV) -> saveValue(() -> {
if (!newV.matches("\\d*")) { if (!newV.matches("\\d*")) {
ctrl.setText(newV.replaceAll(PATTERN_NOT_A_DIGIT, "")); ctrl.setText(newV.replaceAll(PATTERN_NOT_A_DIGIT, ""));
} }
if (!ctrl.getText().isEmpty()) { if (!ctrl.getText().isEmpty()) {
long value = Long.parseLong(ctrl.getText()); var value = Long.parseLong(ctrl.getText());
if (setting.getConverter() != null) { if (setting.getConverter() != null) {
value = (long) setting.getConverter().convertFrom(value); value = (long) setting.getConverter().convertFrom(value);
} }
Field field = Settings.class.getField(setting.getKey()); var field = Settings.class.getField(setting.getKey());
field.set(settings, value); field.set(settings, value); // NOSONAR
if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) { if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) {
runRestartRequiredCallback(); runRestartRequiredCallback();
} }
@ -275,10 +274,10 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
} }
private Node createBooleanProperty(Setting setting) { private Node createBooleanProperty(Setting setting) {
CheckBox ctrl = new CheckBox(); var ctrl = new CheckBox();
ctrl.selectedProperty().addListener((obs, oldV, newV) -> saveValue(() -> { ctrl.selectedProperty().addListener((obs, oldV, newV) -> saveValue(() -> {
Field field = Settings.class.getField(setting.getKey()); var field = Settings.class.getField(setting.getKey());
field.set(settings, newV); field.set(settings, newV); // NOSONAR
if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) { if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) {
runRestartRequiredCallback(); runRestartRequiredCallback();
} }
@ -293,7 +292,7 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
private Node createComboBox(Setting setting) throws NoSuchFieldException, IllegalAccessException { private Node createComboBox(Setting setting) throws NoSuchFieldException, IllegalAccessException {
ListProperty<?> listProp = (ListProperty<?>) setting.getProperty(); ListProperty<?> listProp = (ListProperty<?>) setting.getProperty();
ComboBox<Object> comboBox = new ComboBox(listProp); ComboBox<Object> comboBox = new ComboBox(listProp);
Field field = Settings.class.getField(setting.getKey()); var field = Settings.class.getField(setting.getKey());
Object value = field.get(settings); Object value = field.get(settings);
if (StringUtil.isNotBlank(value.toString())) { if (StringUtil.isNotBlank(value.toString())) {
if (setting.getConverter() != null) { if (setting.getConverter() != null) {
@ -305,9 +304,9 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
comboBox.valueProperty().addListener((obs, oldV, newV) -> saveValue(() -> { comboBox.valueProperty().addListener((obs, oldV, newV) -> saveValue(() -> {
LOG.debug("Saving setting {}", setting.getKey()); LOG.debug("Saving setting {}", setting.getKey());
if (setting.getConverter() != null) { if (setting.getConverter() != null) {
field.set(settings, setting.getConverter().convertFrom(newV)); field.set(settings, setting.getConverter().convertFrom(newV)); // NOSONAR
} else { } else {
field.set(settings, newV); field.set(settings, newV); // NOSONAR
} }
if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) { if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) {
runRestartRequiredCallback(); runRestartRequiredCallback();
@ -330,6 +329,6 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
@FunctionalInterface @FunctionalInterface
private interface Exec { private interface Exec {
public void run() throws Exception; public void run() throws IllegalAccessException, IOException, NoSuchFieldException;
} }
} }

View File

@ -11,7 +11,7 @@ public class DeleteTooShortPaneFactory extends AbstractPostProcessingPaneFactory
@Override @Override
public Preferences doCreatePostProcessorPane(PostProcessor pp) { public Preferences doCreatePostProcessorPane(PostProcessor pp) {
SimpleStringProperty minimumLengthInSeconds = new SimpleStringProperty(null, DeleteTooShort.MIN_LEN_IN_SECS, pp.getConfig().getOrDefault(DeleteTooShort.MIN_LEN_IN_SECS, "10")); var minimumLengthInSeconds = new SimpleStringProperty(null, DeleteTooShort.MIN_LEN_IN_SECS, pp.getConfig().getOrDefault(DeleteTooShort.MIN_LEN_IN_SECS, "10"));
properties.add(minimumLengthInSeconds); properties.add(minimumLengthInSeconds);
return Preferences.of(new MapPreferencesStorage(), return Preferences.of(new MapPreferencesStorage(),

View File

@ -2,7 +2,6 @@ package ctbrec.ui.settings;
import static javafx.scene.control.ButtonType.*; import static javafx.scene.control.ButtonType.*;
import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Type; import java.lang.reflect.Type;
@ -57,7 +56,7 @@ public class IgnoreList extends GridPane {
setVgap(10); setVgap(10);
setPadding(new Insets(20, 10, 10, 10)); setPadding(new Insets(20, 10, 10, 10));
Label headline = new Label("Ignore List"); var headline = new Label("Ignore List");
headline.getStyleClass().add("settings-group-label"); headline.getStyleClass().add("settings-group-label");
add(headline, 0, 0); add(headline, 0, 0);
@ -71,13 +70,13 @@ public class IgnoreList extends GridPane {
add(ignoreListView, 0, 1); add(ignoreListView, 0, 1);
GridPane.setHgrow(ignoreListView, Priority.ALWAYS); GridPane.setHgrow(ignoreListView, Priority.ALWAYS);
Button remove = new Button("Remove"); var remove = new Button("Remove");
remove.setOnAction(evt -> removeSelectedModels()); remove.setOnAction(evt -> removeSelectedModels());
Button exportIgnoreList = new Button("Export"); var exportIgnoreList = new Button("Export");
exportIgnoreList.setOnAction(e -> exportIgnoreList()); exportIgnoreList.setOnAction(e -> exportIgnoreList());
Button importIgnoreList = new Button("Import"); var importIgnoreList = new Button("Import");
importIgnoreList.setOnAction(e -> importIgnoreList()); importIgnoreList.setOnAction(e -> importIgnoreList());
HBox buttons = new HBox(10, remove, exportIgnoreList, importIgnoreList); var buttons = new HBox(10, remove, exportIgnoreList, importIgnoreList);
add(buttons, 0, 2); add(buttons, 0, 2);
buttons.setStyle("-fx-background-color: -fx-background"); // workaround so that the buttons don't shrink buttons.setStyle("-fx-background-color: -fx-background"); // workaround so that the buttons don't shrink
} }
@ -85,7 +84,7 @@ public class IgnoreList extends GridPane {
private void removeSelectedModels() { private void removeSelectedModels() {
List<String> selectedModels = ignoreListView.getSelectionModel().getSelectedItems(); List<String> selectedModels = ignoreListView.getSelectionModel().getSelectedItems();
if (selectedModels.isEmpty()) { if (selectedModels.isEmpty()) {
return; return; // NOSONAR
} else { } else {
Config.getInstance().getSettings().ignoredModels.removeAll(selectedModels); Config.getInstance().getSettings().ignoredModels.removeAll(selectedModels);
ignoreListView.getItems().removeAll(selectedModels); ignoreListView.getItems().removeAll(selectedModels);
@ -110,16 +109,16 @@ public class IgnoreList extends GridPane {
} }
private void exportIgnoreList() { private void exportIgnoreList() {
FileChooser chooser = new FileChooser(); var chooser = new FileChooser();
chooser.setTitle("Export ignore list"); chooser.setTitle("Export ignore list");
chooser.setInitialFileName("ctbrec-ignorelist.json"); chooser.setInitialFileName("ctbrec-ignorelist.json");
File file = chooser.showSaveDialog(null); var file = chooser.showSaveDialog(null);
if (file != null) { if (file != null) {
Moshi moshi = new Moshi.Builder().add(Model.class, new ModelJsonAdapter(sites)).build(); var moshi = new Moshi.Builder().add(Model.class, new ModelJsonAdapter(sites)).build();
Type modelListType = Types.newParameterizedType(List.class, String.class); Type modelListType = Types.newParameterizedType(List.class, String.class);
JsonAdapter<List<String>> adapter = moshi.adapter(modelListType); JsonAdapter<List<String>> adapter = moshi.adapter(modelListType);
adapter = adapter.indent(" "); adapter = adapter.indent(" ");
try (FileOutputStream out = new FileOutputStream(file)) { try (var out = new FileOutputStream(file)) {
String json = adapter.toJson(Config.getInstance().getSettings().ignoredModels); String json = adapter.toJson(Config.getInstance().getSettings().ignoredModels);
out.write(json.getBytes(StandardCharsets.UTF_8)); out.write(json.getBytes(StandardCharsets.UTF_8));
} catch (IOException e) { } catch (IOException e) {
@ -129,20 +128,20 @@ public class IgnoreList extends GridPane {
} }
private void importIgnoreList() { private void importIgnoreList() {
FileChooser chooser = new FileChooser(); var chooser = new FileChooser();
chooser.setTitle("Import ignore list"); chooser.setTitle("Import ignore list");
File file = chooser.showOpenDialog(null); var file = chooser.showOpenDialog(null);
if (file != null) { if (file != null) {
Moshi moshi = new Moshi.Builder().add(Model.class, new ModelJsonAdapter(sites)).build(); var moshi = new Moshi.Builder().add(Model.class, new ModelJsonAdapter(sites)).build();
Type modelListType = Types.newParameterizedType(List.class, String.class); Type modelListType = Types.newParameterizedType(List.class, String.class);
JsonAdapter<List<String>> adapter = moshi.adapter(modelListType); JsonAdapter<List<String>> adapter = moshi.adapter(modelListType);
try { try {
byte[] fileContent = Files.readAllBytes(file.toPath()); byte[] fileContent = Files.readAllBytes(file.toPath());
List<String> ignoredModels = adapter.fromJson(new String(fileContent, StandardCharsets.UTF_8)); List<String> ignoredModels = adapter.fromJson(new String(fileContent, StandardCharsets.UTF_8));
boolean confirmed = true; var confirmed = true;
if (!Config.getInstance().getSettings().ignoredModels.isEmpty()) { if (!Config.getInstance().getSettings().ignoredModels.isEmpty()) {
String msg = "This will replace the existing ignore list! Continue?"; var msg = "This will replace the existing ignore list! Continue?";
AutosizeAlert confirm = new AutosizeAlert(AlertType.CONFIRMATION, msg, getScene(), YES, NO); var confirm = new AutosizeAlert(AlertType.CONFIRMATION, msg, getScene(), YES, NO);
confirm.setTitle("Import ignore list"); confirm.setTitle("Import ignore list");
confirm.setHeaderText("Overwrite ignore list"); confirm.setHeaderText("Overwrite ignore list");
confirm.showAndWait(); confirm.showAndWait();

View File

@ -38,7 +38,7 @@ public class ListSelectionPane<T extends Comparable<T>> extends GridPane {
ObservableList<T> obsAvail = FXCollections.observableArrayList(available); ObservableList<T> obsAvail = FXCollections.observableArrayList(available);
ObservableList<T> obsSel = FXCollections.observableArrayList(selected); ObservableList<T> obsSel = FXCollections.observableArrayList(selected);
for (Iterator<T> iterator = obsAvail.iterator(); iterator.hasNext();) { for (Iterator<T> iterator = obsAvail.iterator(); iterator.hasNext();) {
T t = iterator.next(); var t = iterator.next();
if(obsSel.contains(t)) { if(obsSel.contains(t)) {
iterator.remove(); iterator.remove();
} }
@ -52,13 +52,13 @@ public class ListSelectionPane<T extends Comparable<T>> extends GridPane {
} }
private void createGui() { private void createGui() {
Label labelAvailable = new Label("Available"); var labelAvailable = new Label("Available");
Label labelSelected = new Label("Selected"); var labelSelected = new Label("Selected");
add(labelAvailable, 0, 0); add(labelAvailable, 0, 0);
add(availableListView, 0, 1); add(availableListView, 0, 1);
VBox buttonBox = new VBox(5); var buttonBox = new VBox(5);
buttonBox.getChildren().add(addModel); buttonBox.getChildren().add(addModel);
buttonBox.getChildren().add(removeModel); buttonBox.getChildren().add(removeModel);
buttonBox.setAlignment(Pos.CENTER); buttonBox.setAlignment(Pos.CENTER);

View File

@ -11,7 +11,7 @@ public class MoverPaneFactory extends AbstractPostProcessingPaneFactory {
@Override @Override
public Preferences doCreatePostProcessorPane(PostProcessor pp) { public Preferences doCreatePostProcessorPane(PostProcessor pp) {
SimpleStringProperty pathTemplate = new SimpleStringProperty(null, Move.PATH_TEMPLATE, pp.getConfig().getOrDefault(Move.PATH_TEMPLATE, Move.DEFAULT)); var pathTemplate = new SimpleStringProperty(null, Move.PATH_TEMPLATE, pp.getConfig().getOrDefault(Move.PATH_TEMPLATE, Move.DEFAULT));
properties.add(pathTemplate); properties.add(pathTemplate);
return Preferences.of(new MapPreferencesStorage(), return Preferences.of(new MapPreferencesStorage(),

View File

@ -1,7 +1,21 @@
package ctbrec.ui.settings; package ctbrec.ui.settings;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.Optional;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.recorder.postprocessing.*; import ctbrec.recorder.postprocessing.Copy;
import ctbrec.recorder.postprocessing.CreateContactSheet;
import ctbrec.recorder.postprocessing.DeleteOriginal;
import ctbrec.recorder.postprocessing.DeleteTooShort;
import ctbrec.recorder.postprocessing.Move;
import ctbrec.recorder.postprocessing.PostProcessor;
import ctbrec.recorder.postprocessing.RemoveKeepFile;
import ctbrec.recorder.postprocessing.Remux;
import ctbrec.recorder.postprocessing.Rename;
import ctbrec.recorder.postprocessing.Script;
import ctbrec.ui.controls.Dialogs; import ctbrec.ui.controls.Dialogs;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener; import javafx.collections.ListChangeListener;
@ -16,25 +30,20 @@ import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import javafx.stage.Stage; import javafx.stage.Stage;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.Optional;
public class PostProcessingStepPanel extends GridPane { public class PostProcessingStepPanel extends GridPane {
private final Config config; private final Config config;
private static final Class<?>[] POST_PROCESSOR_CLASSES = new Class<?>[]{ // @formatter: off private static final Class<?>[] POST_PROCESSOR_CLASSES = new Class<?>[]{ // @formatter: off
Copy.class, Copy.class,
Rename.class, Rename.class,
Move.class, Move.class,
Remux.class, Remux.class,
Script.class, Script.class,
DeleteOriginal.class, DeleteOriginal.class,
DeleteTooShort.class, DeleteTooShort.class,
RemoveKeepFile.class, RemoveKeepFile.class,
CreateContactSheet.class CreateContactSheet.class
}; // @formatter: on }; // @formatter: on
ListView<PostProcessor> stepListView; ListView<PostProcessor> stepListView;
@ -61,7 +70,7 @@ public class PostProcessingStepPanel extends GridPane {
add = createAddButton(); add = createAddButton();
remove = createRemoveButton(); remove = createRemoveButton();
edit = createEditButton(); edit = createEditButton();
VBox buttons = new VBox(5, add, edit, up, down, remove); var buttons = new VBox(5, add, edit, up, down, remove);
stepList = FXCollections.observableList(config.getSettings().postProcessors); stepList = FXCollections.observableList(config.getSettings().postProcessors);
stepList.addListener((ListChangeListener<PostProcessor>) change -> { stepList.addListener((ListChangeListener<PostProcessor>) change -> {
@ -78,7 +87,7 @@ public class PostProcessingStepPanel extends GridPane {
add(buttons, 1, 0); add(buttons, 1, 0);
stepListView.getSelectionModel().selectedIndexProperty().addListener((obs, oldV, newV) -> { stepListView.getSelectionModel().selectedIndexProperty().addListener((obs, oldV, newV) -> {
int idx = newV.intValue(); var idx = newV.intValue();
boolean noSelection = idx == -1; boolean noSelection = idx == -1;
up.setDisable(noSelection || idx == 0); up.setDisable(noSelection || idx == 0);
down.setDisable(noSelection || idx == stepList.size() - 1); down.setDisable(noSelection || idx == stepList.size() - 1);
@ -88,7 +97,7 @@ public class PostProcessingStepPanel extends GridPane {
} }
private Button createUpButton() { private Button createUpButton() {
Button button = createButton("\u25B4", "Move step up"); var button = createButton("\u25B4", "Move step up");
button.setOnAction(evt -> { button.setOnAction(evt -> {
int idx = stepListView.getSelectionModel().getSelectedIndex(); int idx = stepListView.getSelectionModel().getSelectedIndex();
PostProcessor selectedItem = stepListView.getSelectionModel().getSelectedItem(); PostProcessor selectedItem = stepListView.getSelectionModel().getSelectedItem();
@ -100,7 +109,7 @@ public class PostProcessingStepPanel extends GridPane {
} }
private Button createDownButton() { private Button createDownButton() {
Button button = createButton("\u25BE", "Move step down"); var button = createButton("\u25BE", "Move step down");
button.setOnAction(evt -> { button.setOnAction(evt -> {
int idx = stepListView.getSelectionModel().getSelectedIndex(); int idx = stepListView.getSelectionModel().getSelectedIndex();
PostProcessor selectedItem = stepListView.getSelectionModel().getSelectedItem(); PostProcessor selectedItem = stepListView.getSelectionModel().getSelectedItem();
@ -112,7 +121,7 @@ public class PostProcessingStepPanel extends GridPane {
} }
private Button createAddButton() { private Button createAddButton() {
Button button = createButton("+", "Add a new step"); var button = createButton("+", "Add a new step");
button.setDisable(false); button.setDisable(false);
button.setOnAction(evt -> { button.setOnAction(evt -> {
PostProcessor[] options = createOptions(); PostProcessor[] options = createOptions();
@ -122,7 +131,7 @@ public class PostProcessingStepPanel extends GridPane {
choice.setResizable(true); choice.setResizable(true);
choice.setWidth(600); choice.setWidth(600);
choice.getDialogPane().setMinWidth(400); choice.getDialogPane().setMinWidth(400);
Stage stage = (Stage) choice.getDialogPane().getScene().getWindow(); var stage = (Stage) choice.getDialogPane().getScene().getWindow();
stage.getScene().getStylesheets().addAll(getScene().getStylesheets()); stage.getScene().getStylesheets().addAll(getScene().getStylesheets());
InputStream icon = Dialogs.class.getResourceAsStream("/icon.png"); InputStream icon = Dialogs.class.getResourceAsStream("/icon.png");
stage.getIcons().add(new Image(icon)); stage.getIcons().add(new Image(icon));
@ -144,8 +153,8 @@ public class PostProcessingStepPanel extends GridPane {
private PostProcessor[] createOptions() { private PostProcessor[] createOptions() {
try { try {
PostProcessor[] options = new PostProcessor[POST_PROCESSOR_CLASSES.length]; var options = new PostProcessor[POST_PROCESSOR_CLASSES.length];
for (int i = 0; i < POST_PROCESSOR_CLASSES.length; i++) { for (var i = 0; i < POST_PROCESSOR_CLASSES.length; i++) {
Class<?> cls = POST_PROCESSOR_CLASSES[i]; Class<?> cls = POST_PROCESSOR_CLASSES[i];
PostProcessor pp; PostProcessor pp;
pp = (PostProcessor) cls.getDeclaredConstructor().newInstance(); pp = (PostProcessor) cls.getDeclaredConstructor().newInstance();
@ -160,7 +169,7 @@ public class PostProcessingStepPanel extends GridPane {
} }
private Button createRemoveButton() { private Button createRemoveButton() {
Button button = createButton("-", "Remove selected step"); var button = createButton("-", "Remove selected step");
button.setOnAction(evt -> { button.setOnAction(evt -> {
PostProcessor selectedItem = stepListView.getSelectionModel().getSelectedItem(); PostProcessor selectedItem = stepListView.getSelectionModel().getSelectedItem();
if (selectedItem != null) { if (selectedItem != null) {
@ -171,7 +180,7 @@ public class PostProcessingStepPanel extends GridPane {
} }
private Button createEditButton() { private Button createEditButton() {
Button button = createButton("\u270E", "Edit selected step"); var button = createButton("\u270E", "Edit selected step");
button.setOnAction(evt -> { button.setOnAction(evt -> {
PostProcessor selectedItem = stepListView.getSelectionModel().getSelectedItem(); PostProcessor selectedItem = stepListView.getSelectionModel().getSelectedItem();
PostProcessingDialogFactory.openEditDialog(selectedItem, getScene(), stepList); PostProcessingDialogFactory.openEditDialog(selectedItem, getScene(), stepList);
@ -182,7 +191,7 @@ public class PostProcessingStepPanel extends GridPane {
} }
private Button createButton(String text, String tooltip) { private Button createButton(String text, String tooltip) {
Button b = new Button(text); var b = new Button(text);
b.setTooltip(new Tooltip(tooltip)); b.setTooltip(new Tooltip(tooltip));
b.setDisable(true); b.setDisable(true);
b.setPrefSize(32, 32); b.setPrefSize(32, 32);

View File

@ -11,8 +11,8 @@ public class RemuxerPaneFactory extends AbstractPostProcessingPaneFactory {
@Override @Override
public Preferences doCreatePostProcessorPane(PostProcessor pp) { public Preferences doCreatePostProcessorPane(PostProcessor pp) {
SimpleStringProperty ffmpegParams = new SimpleStringProperty(null, Remux.FFMPEG_ARGS, pp.getConfig().getOrDefault(Remux.FFMPEG_ARGS, "-c:v copy -c:a copy -movflags faststart -y -f mp4")); var ffmpegParams = new SimpleStringProperty(null, Remux.FFMPEG_ARGS, pp.getConfig().getOrDefault(Remux.FFMPEG_ARGS, "-c:v copy -c:a copy -movflags faststart -y -f mp4"));
SimpleStringProperty fileExt = new SimpleStringProperty(null, Remux.FILE_EXT, pp.getConfig().getOrDefault(Remux.FILE_EXT, "mp4")); var fileExt = new SimpleStringProperty(null, Remux.FILE_EXT, pp.getConfig().getOrDefault(Remux.FILE_EXT, "mp4"));
properties.add(ffmpegParams); properties.add(ffmpegParams);
properties.add(fileExt); properties.add(fileExt);

View File

@ -11,7 +11,7 @@ public class RenamerPaneFactory extends AbstractPostProcessingPaneFactory {
@Override @Override
public Preferences doCreatePostProcessorPane(PostProcessor pp) { public Preferences doCreatePostProcessorPane(PostProcessor pp) {
SimpleStringProperty fileTemplate = new SimpleStringProperty(null, Rename.FILE_NAME_TEMPLATE, pp.getConfig().getOrDefault(Rename.FILE_NAME_TEMPLATE, Rename.DEFAULT)); var fileTemplate = new SimpleStringProperty(null, Rename.FILE_NAME_TEMPLATE, pp.getConfig().getOrDefault(Rename.FILE_NAME_TEMPLATE, Rename.DEFAULT));
properties.add(fileTemplate); properties.add(fileTemplate);
return Preferences.of(new MapPreferencesStorage(), return Preferences.of(new MapPreferencesStorage(),

View File

@ -11,8 +11,8 @@ public class ScriptPaneFactory extends AbstractPostProcessingPaneFactory {
@Override @Override
public Preferences doCreatePostProcessorPane(PostProcessor pp) { public Preferences doCreatePostProcessorPane(PostProcessor pp) {
SimpleStringProperty script = new SimpleStringProperty(null, Script.SCRIPT_EXECUTABLE, pp.getConfig().getOrDefault(Script.SCRIPT_EXECUTABLE, "c:\\users\\johndoe\\somescript")); var script = new SimpleStringProperty(null, Script.SCRIPT_EXECUTABLE, pp.getConfig().getOrDefault(Script.SCRIPT_EXECUTABLE, "c:\\users\\johndoe\\somescript"));
SimpleStringProperty params = new SimpleStringProperty(null, Script.SCRIPT_PARAMS, pp.getConfig().getOrDefault(Script.SCRIPT_PARAMS, "${absolutePath}")); var params = new SimpleStringProperty(null, Script.SCRIPT_PARAMS, pp.getConfig().getOrDefault(Script.SCRIPT_PARAMS, "${absolutePath}"));
properties.add(script); properties.add(script);
properties.add(params); properties.add(params);

View File

@ -203,8 +203,8 @@ public class SettingsTab extends Tab implements TabSelectionListener {
} }
private void createGui() { private void createGui() {
PostProcessingStepPanel postProcessingStepPanel = new PostProcessingStepPanel(config); var postProcessingStepPanel = new PostProcessingStepPanel(config);
Button variablesHelpButton = createHelpButton("Variables", "http://localhost:5689/docs/PostProcessing.md#variables"); var variablesHelpButton = createHelpButton("Variables", "http://localhost:5689/docs/PostProcessing.md#variables");
ignoreList = new IgnoreList(sites); ignoreList = new IgnoreList(sites);
List<Category> siteCategories = new ArrayList<>(); List<Category> siteCategories = new ArrayList<>();
for (Site site : sites) { for (Site site : sites) {
@ -212,8 +212,8 @@ public class SettingsTab extends Tab implements TabSelectionListener {
.ifPresent(configPanel -> siteCategories.add(Category.of(site.getName(), configPanel))); .ifPresent(configPanel -> siteCategories.add(Category.of(site.getName(), configPanel)));
} }
CtbrecPreferencesStorage storage = new CtbrecPreferencesStorage(config); var storage = new CtbrecPreferencesStorage(config);
Preferences prefs = Preferences.of(storage, var prefs = Preferences.of(storage,
Category.of("General", Category.of("General",
Group.of("General", Group.of("General",
Setting.of("User-Agent", httpUserAgent), Setting.of("User-Agent", httpUserAgent),
@ -304,15 +304,15 @@ public class SettingsTab extends Tab implements TabSelectionListener {
storage.setPreferences(prefs); storage.setPreferences(prefs);
preferencesView.setMinSize(800, 400); preferencesView.setMinSize(800, 400);
preferencesView.setPrefSize(1280, 960); preferencesView.setPrefSize(1280, 960);
ScrollPane scrollPane = new ScrollPane(preferencesView); var scrollPane = new ScrollPane(preferencesView);
GridPane container = new GridPane(); var container = new GridPane();
container.add(scrollPane, 0, 0); container.add(scrollPane, 0, 0);
GridPane.setFillWidth(scrollPane, true); GridPane.setFillWidth(scrollPane, true);
GridPane.setFillHeight(scrollPane, true); GridPane.setFillHeight(scrollPane, true);
GridPane.setHgrow(scrollPane, Priority.ALWAYS); GridPane.setHgrow(scrollPane, Priority.ALWAYS);
GridPane.setVgrow(scrollPane, Priority.ALWAYS); GridPane.setVgrow(scrollPane, Priority.ALWAYS);
StackPane stackPane = new StackPane(); var stackPane = new StackPane();
stackPane.getChildren().add(container); stackPane.getChildren().add(container);
restartNotification = new Label("Restart Required"); restartNotification = new Label("Restart Required");
restartNotification.setVisible(false); restartNotification.setVisible(false);
@ -369,7 +369,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
} }
private Button createHelpButton(String text, String url) { private Button createHelpButton(String text, String url) {
Button postProcessingHelpButton = new Button(text); var postProcessingHelpButton = new Button(text);
postProcessingHelpButton.setOnAction(e -> { postProcessingHelpButton.setOnAction(e -> {
new Thread(() -> { new Thread(() -> {
try { try {
@ -446,7 +446,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
Config.getInstance().getSettings().key = key; Config.getInstance().getSettings().key = key;
saveConfig(); saveConfig();
} }
TextInputDialog keyDialog = new TextInputDialog(); var keyDialog = new TextInputDialog();
keyDialog.setResizable(true); keyDialog.setResizable(true);
keyDialog.setTitle("Server Authentication"); keyDialog.setTitle("Server Authentication");
keyDialog.setHeaderText("A key has been generated"); keyDialog.setHeaderText("A key has been generated");
@ -485,7 +485,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
} }
public static GridPane createGridLayout() { public static GridPane createGridLayout() {
GridPane layout = new GridPane(); var layout = new GridPane();
layout.setPadding(new Insets(10)); layout.setPadding(new Insets(10));
layout.setHgap(5); layout.setHgap(5);
layout.setVgap(5); layout.setVgap(5);
@ -500,7 +500,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
fadeIn.setOnFinished(e -> { fadeIn.setOnFinished(e -> {
Transition fadeOut = changeOpacity(restartNotification, 0); Transition fadeOut = changeOpacity(restartNotification, 0);
fadeOut.setOnFinished(e2 -> restartNotification.setVisible(false)); fadeOut.setOnFinished(e2 -> restartNotification.setVisible(false));
PauseTransition pauseTransition = new PauseTransition(Duration.seconds(5)); var pauseTransition = new PauseTransition(Duration.seconds(5));
pauseTransition.setOnFinished(evt -> fadeOut.play()); pauseTransition.setOnFinished(evt -> fadeOut.play());
pauseTransition.play(); pauseTransition.play();
}); });
@ -509,7 +509,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
private static final Duration ANIMATION_DURATION = new Duration(500); private static final Duration ANIMATION_DURATION = new Duration(500);
private Transition changeOpacity(Node node, double opacity) { private Transition changeOpacity(Node node, double opacity) {
FadeTransition transition = new FadeTransition(ANIMATION_DURATION, node); var transition = new FadeTransition(ANIMATION_DURATION, node);
transition.setFromValue(node.getOpacity()); transition.setFromValue(node.getOpacity());
transition.setToValue(opacity); transition.setToValue(opacity);
return transition; return transition;
@ -536,8 +536,8 @@ public class SettingsTab extends Tab implements TabSelectionListener {
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final var prime = 31;
int result = 1; var result = 1;
result = prime * result + value; result = prime * result + value;
return result; return result;
} }
@ -590,8 +590,8 @@ public class SettingsTab extends Tab implements TabSelectionListener {
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final var prime = 31;
int result = 1; var result = 1;
result = prime * result + (int) (value ^ (value >>> 32)); result = prime * result + (int) (value ^ (value >>> 32));
return result; return result;
} }

View File

@ -90,17 +90,17 @@ public class Category {
String q = filter.toLowerCase().trim(); String q = filter.toLowerCase().trim();
if(hasGroups() || hasSubCategories()) { if(hasGroups() || hasSubCategories()) {
return name.toLowerCase().contains(q) return name.toLowerCase().contains(q)
| groupsContains(q) || groupsContains(q)
| subCategoriesContains(q); || subCategoriesContains(q);
} else { } else {
return name.toLowerCase().contains(q) return name.toLowerCase().contains(q)
| guiContains(q); || guiContains(q);
} }
} }
private boolean subCategoriesContains(String filter) { private boolean subCategoriesContains(String filter) {
boolean contains = false; var contains = false;
if (subCategories != null) { if (subCategories != null) {
for (Category category : subCategories) { for (Category category : subCategories) {
if (category.contains(filter)) { if (category.contains(filter)) {
@ -112,7 +112,7 @@ public class Category {
} }
private boolean groupsContains(String filter) { private boolean groupsContains(String filter) {
boolean contains = false; var contains = false;
if (groups != null) { if (groups != null) {
for (Group group : groups) { for (Group group : groups) {
if (group.contains(filter)) { if (group.contains(filter)) {
@ -131,9 +131,9 @@ public class Category {
} }
private boolean nodeContains(Node node, String filter) { private boolean nodeContains(Node node, String filter) {
boolean contains = false; var contains = false;
if (node instanceof Pane) { if (node instanceof Pane) {
Pane pane = (Pane) node; var pane = (Pane) node;
for (Node child : pane.getChildren()) { for (Node child : pane.getChildren()) {
contains |= nodeContains(child, filter); contains |= nodeContains(child, filter);
} }

View File

@ -34,11 +34,11 @@ public class Group {
} }
public boolean contains(String filter) { public boolean contains(String filter) {
return name.toLowerCase().contains(filter) | settingsContain(filter); return name.toLowerCase().contains(filter) || settingsContain(filter);
} }
private boolean settingsContain(String filter) { private boolean settingsContain(String filter) {
boolean contains = false; var contains = false;
if (settings != null) { if (settings != null) {
for (Setting setting : settings) { for (Setting setting : settings) {
if (setting.contains(filter)) { if (setting.contains(filter)) {

View File

@ -16,7 +16,7 @@ class HighlightingSupport {
private HighlightingSupport() {} private HighlightingSupport() {}
static void highlightMatches(Category cat, String filter) { static void highlightMatches(Category cat, String filter) {
Node node = cat.getGuiOrElse(Label::new); var node = cat.getGuiOrElse(Label::new);
highlightMatchess(node, filter); highlightMatchess(node, filter);
if(cat.hasSubCategories()) { if(cat.hasSubCategories()) {
for (Category sub : cat.getSubCategories()) { for (Category sub : cat.getSubCategories()) {
@ -26,9 +26,9 @@ class HighlightingSupport {
} }
static void highlightMatchess(Node node, String filter) { static void highlightMatchess(Node node, String filter) {
boolean contains = false; var contains = false;
if (node instanceof Pane) { if (node instanceof Pane) {
Pane pane = (Pane) node; var pane = (Pane) node;
for (Node child : pane.getChildren()) { for (Node child : pane.getChildren()) {
highlightMatchess(child, filter); highlightMatchess(child, filter);
} }
@ -51,9 +51,9 @@ class HighlightingSupport {
} }
private static boolean labelControlContains(Label lbl, String filter) { private static boolean labelControlContains(Label lbl, String filter) {
boolean contains = false; var contains = false;
if (lbl.labelForProperty().get() != null) { if (lbl.labelForProperty().get() != null) {
Node labeledNode = lbl.labelForProperty().get(); var labeledNode = lbl.labelForProperty().get();
contains |= labeledNode.toString().toLowerCase().contains(filter); contains |= labeledNode.toString().toLowerCase().contains(filter);
if (labeledNode instanceof Control) { if (labeledNode instanceof Control) {
contains |= ofNullable(((Control) labeledNode).getTooltip()).map(Tooltip::getText).orElse("").toLowerCase().contains(filter); contains |= ofNullable(((Control) labeledNode).getTooltip()).map(Tooltip::getText).orElse("").toLowerCase().contains(filter);
@ -66,7 +66,7 @@ class HighlightingSupport {
} }
static void removeHighlights(Category cat) { static void removeHighlights(Category cat) {
Node node = cat.getGuiOrElse(Label::new); var node = cat.getGuiOrElse(Label::new);
removeHighlights(node); removeHighlights(node);
if(cat.hasSubCategories()) { if(cat.hasSubCategories()) {
for (Category sub : cat.getSubCategories()) { for (Category sub : cat.getSubCategories()) {

View File

@ -72,17 +72,17 @@ public class Preferences {
} }
public Region getView(boolean withNavigation) { public Region getView(boolean withNavigation) {
SearchBox search = new SearchBox(true); var search = new SearchBox(true);
search.textProperty().addListener(this::filterTree); search.textProperty().addListener(this::filterTree);
TreeItem<Category> categoryTreeItems = createCategoryTree(categories, new TreeItem<>(), null); TreeItem<Category> categoryTreeItems = createCategoryTree(categories, new TreeItem<>(), null);
categoryTree = new TreeView<>(categoryTreeItems); categoryTree = new TreeView<>(categoryTreeItems);
categoryTree.showRootProperty().set(false); categoryTree.showRootProperty().set(false);
VBox leftSide = new VBox(search, categoryTree); var leftSide = new VBox(search, categoryTree);
VBox.setVgrow(categoryTree, Priority.ALWAYS); VBox.setVgrow(categoryTree, Priority.ALWAYS);
VBox.setMargin(search, new Insets(2)); VBox.setMargin(search, new Insets(2));
VBox.setMargin(categoryTree, new Insets(2)); VBox.setMargin(categoryTree, new Insets(2));
BorderPane main = new BorderPane(); var main = new BorderPane();
if (withNavigation) { if (withNavigation) {
main.setLeft(leftSide); main.setLeft(leftSide);
} }
@ -149,9 +149,9 @@ public class Preferences {
} }
private Node createPaneWithGroups(Category cat) throws Exception { private Node createPaneWithGroups(Category cat) throws Exception {
VBox pane = new VBox(); var pane = new VBox();
for (Group grp : cat.getGroups()) { for (Group grp : cat.getGroups()) {
Label groupLabel = new Label(grp.getName()); var groupLabel = new Label(grp.getName());
groupLabel.getStyleClass().add("settings-group-label"); groupLabel.getStyleClass().add("settings-group-label");
VBox.setMargin(groupLabel, new Insets(20, 0, 10, 20)); VBox.setMargin(groupLabel, new Insets(20, 0, 10, 20));
pane.getChildren().add(groupLabel); pane.getChildren().add(groupLabel);
@ -163,13 +163,13 @@ public class Preferences {
} }
private Node createGrid(Setting[] settings) throws Exception { private Node createGrid(Setting[] settings) throws Exception {
GridPane pane = new GridPane(); var pane = new GridPane();
pane.setHgap(2); pane.setHgap(2);
pane.vgapProperty().bind(pane.hgapProperty()); pane.vgapProperty().bind(pane.hgapProperty());
int row = 0; var row = 0;
for (Setting setting : settings) { for (Setting setting : settings) {
Node node = setting.getGui(); var node = setting.getGui();
Label label = new Label(setting.getName()); var label = new Label(setting.getName());
label.setMinHeight(34); label.setMinHeight(34);
label.labelForProperty().set(node); label.labelForProperty().set(node);
label.setTooltip(new Tooltip(setting.getName())); label.setTooltip(new Tooltip(setting.getName()));
@ -226,7 +226,7 @@ public class Preferences {
} }
public Optional<Setting> getSetting(String key) { public Optional<Setting> getSetting(String key) {
SettingSearchVisitor search = new SettingSearchVisitor(key); var search = new SettingSearchVisitor(key);
traverse(search); traverse(search);
return search.getResult(); return search.getResult();
} }

View File

@ -9,5 +9,5 @@ public interface PreferencesStorage {
void save(Preferences preferences) throws IOException; void save(Preferences preferences) throws IOException;
void load(Preferences preferences); void load(Preferences preferences);
Node createGui(Setting setting) throws Exception; Node createGui(Setting setting) throws NoSuchFieldException, IllegalAccessException;
} }

View File

@ -3,6 +3,7 @@ package ctbrec.ui.settings.api;
import static java.util.Optional.*; import static java.util.Optional.*;
import ctbrec.StringUtil; import ctbrec.StringUtil;
import ctbrec.ui.controls.Dialogs;
import javafx.beans.property.Property; import javafx.beans.property.Property;
import javafx.beans.value.ChangeListener; import javafx.beans.value.ChangeListener;
import javafx.scene.Node; import javafx.scene.Node;
@ -35,13 +36,13 @@ public class Setting {
} }
public static Setting of(String name, Property<?> property, String tooltip) { public static Setting of(String name, Property<?> property, String tooltip) {
Setting setting = new Setting(name, property); var setting = new Setting(name, property);
setting.tooltip = tooltip; setting.tooltip = tooltip;
return setting; return setting;
} }
public static Setting of(String name, Node gui) { public static Setting of(String name, Node gui) {
Setting setting = new Setting(name, gui); var setting = new Setting(name, gui);
return setting; return setting;
} }
@ -79,12 +80,16 @@ public class Setting {
return property; return property;
} }
public Node getGui() throws Exception { public Node getGui() {
if (gui == null) { if (gui == null) {
gui = preferencesStorage.createGui(this); try {
if (gui instanceof Control && StringUtil.isNotBlank(tooltip)) { gui = preferencesStorage.createGui(this);
Control control = (Control) gui; if (gui instanceof Control && StringUtil.isNotBlank(tooltip)) {
control.setTooltip(new Tooltip(tooltip)); var control = (Control) gui;
control.setTooltip(new Tooltip(tooltip));
}
} catch (NoSuchFieldException | IllegalAccessException e) {
Dialogs.showError("Error", "Error creating settings GUI", e);
} }
} }
return gui; return gui;

View File

@ -9,7 +9,7 @@ import ctbrec.Config;
public abstract class AbstractConfigUI implements ConfigUI { public abstract class AbstractConfigUI implements ConfigUI {
private static final transient Logger LOG = LoggerFactory.getLogger(AbstractConfigUI.class); private static final Logger LOG = LoggerFactory.getLogger(AbstractConfigUI.class);
protected void save() { protected void save() {
try { try {

View File

@ -1,7 +1,6 @@
package ctbrec.ui.sites.bonga; package ctbrec.ui.sites.bonga;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.Settings;
import ctbrec.sites.bonga.BongaCams; import ctbrec.sites.bonga.BongaCams;
import ctbrec.ui.DesktopIntegration; import ctbrec.ui.DesktopIntegration;
import ctbrec.ui.settings.SettingsTab; import ctbrec.ui.settings.SettingsTab;
@ -26,14 +25,14 @@ public class BongaCamsConfigUI extends AbstractConfigUI {
@Override @Override
public Parent createConfigPanel() { public Parent createConfigPanel() {
GridPane layout = SettingsTab.createGridLayout(); GridPane layout = SettingsTab.createGridLayout();
Settings settings = Config.getInstance().getSettings(); var settings = Config.getInstance().getSettings();
int row = 0; var row = 0;
Label l = new Label("Active"); var l = new Label("Active");
layout.add(l, 0, row); layout.add(l, 0, row);
CheckBox enabled = new CheckBox(); var enabled = new CheckBox();
enabled.setSelected(!settings.disabledSites.contains(bongaCams.getName())); enabled.setSelected(!settings.disabledSites.contains(bongaCams.getName()));
enabled.setOnAction((e) -> { enabled.setOnAction(e -> {
if(enabled.isSelected()) { if(enabled.isSelected()) {
settings.disabledSites.remove(bongaCams.getName()); settings.disabledSites.remove(bongaCams.getName());
} else { } else {
@ -45,7 +44,7 @@ public class BongaCamsConfigUI extends AbstractConfigUI {
layout.add(enabled, 1, row++); layout.add(enabled, 1, row++);
layout.add(new Label("BongaCams User"), 0, row); layout.add(new Label("BongaCams User"), 0, row);
TextField username = new TextField(settings.bongaUsername); var username = new TextField(settings.bongaUsername);
username.setPrefWidth(300); username.setPrefWidth(300);
username.textProperty().addListener((ob, o, n) -> { username.textProperty().addListener((ob, o, n) -> {
if(!n.equals(Config.getInstance().getSettings().bongaUsername)) { if(!n.equals(Config.getInstance().getSettings().bongaUsername)) {
@ -60,7 +59,7 @@ public class BongaCamsConfigUI extends AbstractConfigUI {
layout.add(username, 1, row++); layout.add(username, 1, row++);
layout.add(new Label("BongaCams Password"), 0, row); layout.add(new Label("BongaCams Password"), 0, row);
PasswordField password = new PasswordField(); var password = new PasswordField();
password.setText(settings.bongaPassword); password.setText(settings.bongaPassword);
password.textProperty().addListener((ob, o, n) -> { password.textProperty().addListener((ob, o, n) -> {
if(!n.equals(Config.getInstance().getSettings().bongaPassword)) { if(!n.equals(Config.getInstance().getSettings().bongaPassword)) {
@ -75,7 +74,7 @@ public class BongaCamsConfigUI extends AbstractConfigUI {
layout.add(password, 1, row++); layout.add(password, 1, row++);
layout.add(new Label("Bongacams Base URL"), 0, row); layout.add(new Label("Bongacams Base URL"), 0, row);
TextField baseUrl = new TextField(); var baseUrl = new TextField();
baseUrl.setText(Config.getInstance().getSettings().bongacamsBaseUrl); baseUrl.setText(Config.getInstance().getSettings().bongacamsBaseUrl);
baseUrl.textProperty().addListener((ob, o, n) -> { baseUrl.textProperty().addListener((ob, o, n) -> {
Config.getInstance().getSettings().bongacamsBaseUrl = baseUrl.getText(); Config.getInstance().getSettings().bongacamsBaseUrl = baseUrl.getText();
@ -86,9 +85,9 @@ public class BongaCamsConfigUI extends AbstractConfigUI {
GridPane.setColumnSpan(baseUrl, 2); GridPane.setColumnSpan(baseUrl, 2);
layout.add(baseUrl, 1, row++); layout.add(baseUrl, 1, row++);
Button createAccount = new Button("Create new Account"); var createAccount = new Button("Create new Account");
createAccount.setOnAction((e) -> DesktopIntegration.open(bongaCams.getAffiliateLink())); createAccount.setOnAction(e -> DesktopIntegration.open(bongaCams.getAffiliateLink()));
layout.add(createAccount, 1, row++); layout.add(createAccount, 1, row);
GridPane.setColumnSpan(createAccount, 2); GridPane.setColumnSpan(createAccount, 2);
GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN)); GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN)); GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));

View File

@ -7,7 +7,6 @@ import java.util.Collections;
import java.util.Objects; import java.util.Objects;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -32,11 +31,11 @@ public class BongaCamsElectronLoginDialog {
this.cookieJar = cookieJar; this.cookieJar = cookieJar;
browser = ExternalBrowser.getInstance(); browser = ExternalBrowser.getInstance();
try { try {
JSONObject config = new JSONObject(); var config = new JSONObject();
config.put("url", URL); config.put("url", URL);
config.put("w", 640); config.put("w", 640);
config.put("h", 480); config.put("h", 480);
JSONObject msg = new JSONObject(); var msg = new JSONObject();
msg.put("config", config); msg.put("config", config);
browser.run(msg, msgHandler); browser.run(msg, msgHandler);
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -51,9 +50,9 @@ public class BongaCamsElectronLoginDialog {
if(!line.startsWith("{")) { if(!line.startsWith("{")) {
LOG.error("Didn't received a JSON object {}", line); LOG.error("Didn't received a JSON object {}", line);
} else { } else {
JSONObject json = new JSONObject(line); var json = new JSONObject(line);
if(json.has("url")) { if(json.has("url")) {
String url = json.getString("url"); var url = json.getString("url");
if(url.endsWith("/login")) { if(url.endsWith("/login")) {
try { try {
Thread.sleep(500); Thread.sleep(500);
@ -66,7 +65,7 @@ public class BongaCamsElectronLoginDialog {
password = password.replace("'", "\\'"); password = password.replace("'", "\\'");
browser.executeJavaScript("document.getElementById('log_in_password').value = '" + password + "';"); browser.executeJavaScript("document.getElementById('log_in_password').value = '" + password + "';");
} }
String[] simplify = new String[] { var simplify = new String[] {
"$('div[class~=\"page_header\"]').css('display','none');", "$('div[class~=\"page_header\"]').css('display','none');",
"$('div[class~=\"header_bar\"]').css('display','none')", "$('div[class~=\"header_bar\"]').css('display','none')",
"$('footer').css('display','none');", "$('footer').css('display','none');",
@ -76,15 +75,18 @@ public class BongaCamsElectronLoginDialog {
for (String js : simplify) { for (String js : simplify) {
browser.executeJavaScript(js); browser.executeJavaScript(js);
} }
} catch(InterruptedException e) {
Thread.currentThread().interrupt();
LOG.warn("Couldn't auto fill username and password for BongaCams", e);
} catch(Exception e) { } catch(Exception e) {
LOG.warn("Couldn't auto fill username and password for BongaCams", e); LOG.warn("Couldn't auto fill username and password for BongaCams", e);
} }
} }
if(json.has("cookies")) { if(json.has("cookies")) {
JSONArray cookiesFromBrowser = json.getJSONArray("cookies"); var cookiesFromBrowser = json.getJSONArray("cookies");
for (int i = 0; i < cookiesFromBrowser.length(); i++) { for (var i = 0; i < cookiesFromBrowser.length(); i++) {
JSONObject cookie = cookiesFromBrowser.getJSONObject(i); var cookie = cookiesFromBrowser.getJSONObject(i);
if(cookie.getString("domain").contains(DOMAIN)) { if(cookie.getString("domain").contains(DOMAIN)) {
Builder b = new Cookie.Builder() Builder b = new Cookie.Builder()
.path(cookie.getString("path")) .path(cookie.getString("path"))

View File

@ -11,7 +11,7 @@ import ctbrec.ui.tabs.ThumbOverviewTab;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
public class BongaCamsTabProvider extends TabProvider { public class BongaCamsTabProvider implements TabProvider {
private BongaCams bongaCams; private BongaCams bongaCams;
private Recorder recorder; private Recorder recorder;
@ -28,7 +28,7 @@ public class BongaCamsTabProvider extends TabProvider {
// female // female
String url = BongaCams.baseUrl + "/tools/listing_v3.php?livetab=female&online_only=true&is_mobile=true&offset="; String url = BongaCams.baseUrl + "/tools/listing_v3.php?livetab=female&online_only=true&is_mobile=true&offset=";
BongaCamsUpdateService updateService = new BongaCamsUpdateService(bongaCams, url); var updateService = new BongaCamsUpdateService(bongaCams, url);
tabs.add(createTab("Female", updateService)); tabs.add(createTab("Female", updateService));
// male // male
@ -67,7 +67,7 @@ public class BongaCamsTabProvider extends TabProvider {
} }
private Tab createTab(String title, PaginatedScheduledService updateService) { private Tab createTab(String title, PaginatedScheduledService updateService) {
ThumbOverviewTab tab = new ThumbOverviewTab(title, updateService, bongaCams); var tab = new ThumbOverviewTab(title, updateService, bongaCams);
tab.setRecorder(recorder); tab.setRecorder(recorder);
return tab; return tab;
} }

View File

@ -19,7 +19,6 @@ import ctbrec.sites.bonga.BongaCamsModel;
import ctbrec.ui.tabs.PaginatedScheduledService; import ctbrec.ui.tabs.PaginatedScheduledService;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response;
public class BongaCamsUpdateService extends PaginatedScheduledService { public class BongaCamsUpdateService extends PaginatedScheduledService {
@ -38,48 +37,56 @@ public class BongaCamsUpdateService extends PaginatedScheduledService {
return new Task<List<Model>>() { return new Task<List<Model>>() {
@Override @Override
public List<Model> call() throws IOException { public List<Model> call() throws IOException {
String pageUrl = url + ((page-1) * 36); return loadModelList();
LOG.debug("Fetching page {}", pageUrl);
Request request = new Request.Builder()
.url(pageUrl)
.addHeader(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.addHeader(ACCEPT, MIMETYPE_APPLICATION_JSON)
.addHeader(ACCEPT, Locale.ENGLISH.getLanguage())
.addHeader(REFERER, bongaCams.getBaseUrl())
.addHeader(X_REQUESTED_WITH, XML_HTTP_REQUEST)
.build();
Response response = bongaCams.getHttpClient().execute(request);
if (response.isSuccessful()) {
String content = response.body().string();
List<Model> models = new ArrayList<>();
JSONObject json = new JSONObject(content);
//LOG.debug(json.toString(2));
if (json.optString("status").equals("success")) {
JSONArray jsonModels = json.getJSONArray("models");
for (int i = 0; i < jsonModels.length(); i++) {
JSONObject m = jsonModels.getJSONObject(i);
String name = m.optString("username");
if (name.isEmpty()) {
continue;
}
BongaCamsModel model = (BongaCamsModel) bongaCams.createModel(name);
model.mapOnlineState(m.optString("room"));
model.setOnline(m.optInt("viewers") > 0);
model.setPreview("https:" + m.getString("thumb_image").replace("{ext}", "jpg"));
if (m.has("display_name")) {
model.setDisplayName(m.getString("display_name"));
}
model.setDescription(m.optString("topic"));
models.add(model);
}
}
return models;
} else {
int code = response.code();
response.close();
throw new IOException("HTTP status " + code);
}
} }
}; };
} }
private List<Model> loadModelList() throws IOException {
String pageUrl = url + ((page-1) * 36);
LOG.debug("Fetching page {}", pageUrl);
var request = new Request.Builder()
.url(pageUrl)
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.header(ACCEPT, MIMETYPE_APPLICATION_JSON)
.header(ACCEPT, Locale.ENGLISH.getLanguage())
.header(REFERER, bongaCams.getBaseUrl())
.header(X_REQUESTED_WITH, XML_HTTP_REQUEST)
.build();
try (var response = bongaCams.getHttpClient().execute(request)) {
if (response.isSuccessful()) {
var content = response.body().string();
List<Model> models = new ArrayList<>();
var json = new JSONObject(content);
if (json.optString("status").equals("success")) {
var jsonModels = json.getJSONArray("models");
parseModels(jsonModels, models);
}
return models;
} else {
int code = response.code();
throw new IOException("HTTP status " + code);
}
}
}
private void parseModels(JSONArray jsonModels, List<Model> models) {
for (var i = 0; i < jsonModels.length(); i++) {
var m = jsonModels.getJSONObject(i);
var name = m.optString("username");
if (name.isEmpty()) {
continue;
}
BongaCamsModel model = (BongaCamsModel) bongaCams.createModel(name);
model.mapOnlineState(m.optString("room"));
model.setOnline(m.optInt("viewers") > 0);
model.setPreview("https:" + m.getString("thumb_image").replace("{ext}", "jpg"));
if (m.has("display_name")) {
model.setDisplayName(m.getString("display_name"));
}
model.setDescription(m.optString("topic"));
models.add(model);
}
}
} }

View File

@ -1,7 +1,6 @@
package ctbrec.ui.sites.cam4; package ctbrec.ui.sites.cam4;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.Settings;
import ctbrec.sites.cam4.Cam4; import ctbrec.sites.cam4.Cam4;
import ctbrec.ui.DesktopIntegration; import ctbrec.ui.DesktopIntegration;
import ctbrec.ui.settings.SettingsTab; import ctbrec.ui.settings.SettingsTab;
@ -25,15 +24,15 @@ public class Cam4ConfigUI extends AbstractConfigUI {
@Override @Override
public Parent createConfigPanel() { public Parent createConfigPanel() {
GridPane layout = SettingsTab.createGridLayout(); var layout = SettingsTab.createGridLayout();
Settings settings = Config.getInstance().getSettings(); var settings = Config.getInstance().getSettings();
int row = 0; var row = 0;
Label l = new Label("Active"); var l = new Label("Active");
layout.add(l, 0, row); layout.add(l, 0, row);
CheckBox enabled = new CheckBox(); var enabled = new CheckBox();
enabled.setSelected(!settings.disabledSites.contains(cam4.getName())); enabled.setSelected(!settings.disabledSites.contains(cam4.getName()));
enabled.setOnAction((e) -> { enabled.setOnAction(e -> {
if(enabled.isSelected()) { if(enabled.isSelected()) {
settings.disabledSites.remove(cam4.getName()); settings.disabledSites.remove(cam4.getName());
} else { } else {
@ -45,7 +44,7 @@ public class Cam4ConfigUI extends AbstractConfigUI {
layout.add(enabled, 1, row++); layout.add(enabled, 1, row++);
layout.add(new Label("Cam4 User"), 0, row); layout.add(new Label("Cam4 User"), 0, row);
TextField username = new TextField(Config.getInstance().getSettings().cam4Username); var username = new TextField(Config.getInstance().getSettings().cam4Username);
username.textProperty().addListener((ob, o, n) -> { username.textProperty().addListener((ob, o, n) -> {
if(!n.equals(Config.getInstance().getSettings().cam4Username)) { if(!n.equals(Config.getInstance().getSettings().cam4Username)) {
Config.getInstance().getSettings().cam4Username = username.getText(); Config.getInstance().getSettings().cam4Username = username.getText();
@ -59,7 +58,7 @@ public class Cam4ConfigUI extends AbstractConfigUI {
layout.add(username, 1, row++); layout.add(username, 1, row++);
layout.add(new Label("Cam4 Password"), 0, row); layout.add(new Label("Cam4 Password"), 0, row);
PasswordField password = new PasswordField(); var password = new PasswordField();
password.setText(Config.getInstance().getSettings().cam4Password); password.setText(Config.getInstance().getSettings().cam4Password);
password.textProperty().addListener((ob, o, n) -> { password.textProperty().addListener((ob, o, n) -> {
if(!n.equals(Config.getInstance().getSettings().cam4Password)) { if(!n.equals(Config.getInstance().getSettings().cam4Password)) {
@ -73,9 +72,9 @@ public class Cam4ConfigUI extends AbstractConfigUI {
GridPane.setColumnSpan(password, 2); GridPane.setColumnSpan(password, 2);
layout.add(password, 1, row++); layout.add(password, 1, row++);
Button createAccount = new Button("Create new Account"); var createAccount = new Button("Create new Account");
createAccount.setOnAction((e) -> DesktopIntegration.open(Cam4.AFFILIATE_LINK)); createAccount.setOnAction(e -> DesktopIntegration.open(Cam4.AFFILIATE_LINK));
layout.add(createAccount, 1, row++); layout.add(createAccount, 1, row);
GridPane.setColumnSpan(createAccount, 2); GridPane.setColumnSpan(createAccount, 2);
GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN)); GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN)); GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));

View File

@ -7,7 +7,6 @@ import java.util.Collections;
import java.util.Objects; import java.util.Objects;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -32,11 +31,11 @@ public class Cam4ElectronLoginDialog {
this.cookieJar = cookieJar; this.cookieJar = cookieJar;
browser = ExternalBrowser.getInstance(); browser = ExternalBrowser.getInstance();
try { try {
JSONObject config = new JSONObject(); var config = new JSONObject();
config.put("url", URL); config.put("url", URL);
config.put("w", 480); config.put("w", 480);
config.put("h", 640); config.put("h", 640);
JSONObject msg = new JSONObject(); var msg = new JSONObject();
msg.put("config", config); msg.put("config", config);
browser.run(msg, msgHandler); browser.run(msg, msgHandler);
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -51,9 +50,9 @@ public class Cam4ElectronLoginDialog {
if(!line.startsWith("{")) { if(!line.startsWith("{")) {
LOG.error("Didn't received a JSON object {}", line); LOG.error("Didn't received a JSON object {}", line);
} else { } else {
JSONObject json = new JSONObject(line); var json = new JSONObject(line);
if(json.has("url")) { if (json.has("url")) {
String url = json.getString("url"); var url = json.getString("url");
if(url.endsWith("/login")) { if(url.endsWith("/login")) {
try { try {
@ -76,16 +75,16 @@ public class Cam4ElectronLoginDialog {
} }
if(json.has("cookies")) { if(json.has("cookies")) {
JSONArray cookiesFromBrowser = json.getJSONArray("cookies"); var cookiesFromBrowser = json.getJSONArray("cookies");
try { try {
for (int i = 0; i < cookiesFromBrowser.length(); i++) { for (var i = 0; i < cookiesFromBrowser.length(); i++) {
JSONObject cookie = cookiesFromBrowser.getJSONObject(i); var cookie = cookiesFromBrowser.getJSONObject(i);
if(cookie.getString("domain").contains("cam4")) { if(cookie.getString("domain").contains("cam4")) {
String domain = cookie.getString("domain"); var domain = cookie.getString("domain");
if(domain.startsWith(".")) { if(domain.startsWith(".")) {
domain = domain.substring(1); domain = domain.substring(1);
} }
Cookie c = createCookie(domain, cookie); var c = createCookie(domain, cookie);
cookieJar.saveFromResponse(HttpUrl.parse(url), Collections.singletonList(c)); cookieJar.saveFromResponse(HttpUrl.parse(url), Collections.singletonList(c));
c = createCookie("cam4.com", cookie); c = createCookie("cam4.com", cookie);
cookieJar.saveFromResponse(HttpUrl.parse(Cam4.BASE_URI), Collections.singletonList(c)); cookieJar.saveFromResponse(HttpUrl.parse(Cam4.BASE_URI), Collections.singletonList(c));

View File

@ -29,17 +29,17 @@ public class Cam4FollowedTab extends ThumbOverviewTab implements FollowedTab {
} }
private void addOnlineOfflineSelector() { private void addOnlineOfflineSelector() {
ToggleGroup group = new ToggleGroup(); var group = new ToggleGroup();
RadioButton online = new RadioButton("online"); var online = new RadioButton("online");
online.setToggleGroup(group); online.setToggleGroup(group);
RadioButton offline = new RadioButton("offline"); var offline = new RadioButton("offline");
offline.setToggleGroup(group); offline.setToggleGroup(group);
pagination.getChildren().add(online); pagination.getChildren().add(online);
pagination.getChildren().add(offline); pagination.getChildren().add(offline);
HBox.setMargin(online, new Insets(5,5,5,40)); HBox.setMargin(online, new Insets(5,5,5,40));
HBox.setMargin(offline, new Insets(5,5,5,5)); HBox.setMargin(offline, new Insets(5,5,5,5));
online.setSelected(true); online.setSelected(true);
group.selectedToggleProperty().addListener((e) -> { group.selectedToggleProperty().addListener(e -> {
((Cam4FollowedUpdateService)updateService).setShowOnline(online.isSelected()); ((Cam4FollowedUpdateService)updateService).setShowOnline(online.isSelected());
queue.clear(); queue.clear();
updateService.restart(); updateService.restart();
@ -66,10 +66,8 @@ public class Cam4FollowedTab extends ThumbOverviewTab implements FollowedTab {
public void setScene(Scene scene) { public void setScene(Scene scene) {
scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> { scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if(this.isSelected()) { if (this.isSelected() && event.getCode() == KeyCode.DELETE) {
if(event.getCode() == KeyCode.DELETE) { follow(selectedThumbCells, false);
follow(selectedThumbCells, false);
}
} }
}); });
} }

View File

@ -6,7 +6,6 @@ import java.util.List;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import ctbrec.Model; import ctbrec.Model;
@ -17,7 +16,6 @@ import ctbrec.ui.SiteUiFactory;
import ctbrec.ui.tabs.PaginatedScheduledService; import ctbrec.ui.tabs.PaginatedScheduledService;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response;
public class Cam4FollowedUpdateService extends PaginatedScheduledService { public class Cam4FollowedUpdateService extends PaginatedScheduledService {
@ -27,7 +25,7 @@ public class Cam4FollowedUpdateService extends PaginatedScheduledService {
public Cam4FollowedUpdateService(Cam4 site) { public Cam4FollowedUpdateService(Cam4 site) {
this.site = site; this.site = site;
ExecutorService executor = Executors.newSingleThreadExecutor(r -> { ExecutorService executor = Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r); var t = new Thread(r);
t.setDaemon(true); t.setDaemon(true);
t.setName("ThumbOverviewTab UpdateService"); t.setName("ThumbOverviewTab UpdateService");
return t; return t;
@ -40,37 +38,45 @@ public class Cam4FollowedUpdateService extends PaginatedScheduledService {
return new Task<List<Model>>() { return new Task<List<Model>>() {
@Override @Override
public List<Model> call() throws IOException { public List<Model> call() throws IOException {
// login first return loadModelList();
SiteUiFactory.getUi(site).login();
List<Model> models = new ArrayList<>();
String url = site.getBaseUrl() + "/directoryCams?directoryJson=true&online=" + showOnline + "&url=true&friends=true&favorites=true&resultsPerPage=90";
Request req = new Request.Builder().url(url).build();
try (Response response = site.getHttpClient().execute(req)) {
if (response.isSuccessful()) {
String content = response.body().string();
JSONObject json = new JSONObject(content);
JSONArray users = json.getJSONArray("users");
for (int i = 0; i < users.length(); i++) {
JSONObject modelJson = users.getJSONObject(i);
String username = modelJson.optString("username");
Cam4Model model = site.createModel(username);
model.setPreview(modelJson.optString("snapshotImageLink"));
model.setOnlineStateByShowType(modelJson.optString("showType"));
model.setDescription(modelJson.optString("statusMessage"));
if (modelJson.has("hlsPreviewUrl")) {
model.setPlaylistUrl(modelJson.getString("hlsPreviewUrl"));
}
models.add(model);
}
return models;
} else {
throw new HttpException(response.code(), response.message());
}
}
} }
}; };
} }
private List<Model> loadModelList() throws IOException {
// login first
SiteUiFactory.getUi(site).login();
String url = site.getBaseUrl() + "/directoryCams?directoryJson=true&online=" + showOnline + "&url=true&friends=true&favorites=true&resultsPerPage=90";
Request req = new Request.Builder().url(url).build();
try (var response = site.getHttpClient().execute(req)) {
if (response.isSuccessful()) {
var content = response.body().string();
return parseModels(content);
} else {
throw new HttpException(response.code(), response.message());
}
}
}
private List<Model> parseModels(String content) {
List<Model> models = new ArrayList<>();
var json = new JSONObject(content);
var users = json.getJSONArray("users");
for (var i = 0; i < users.length(); i++) {
var modelJson = users.getJSONObject(i);
var username = modelJson.optString("username");
Cam4Model model = site.createModel(username);
model.setPreview(modelJson.optString("snapshotImageLink"));
model.setOnlineStateByShowType(modelJson.optString("showType"));
model.setDescription(modelJson.optString("statusMessage"));
if (modelJson.has("hlsPreviewUrl")) {
model.setPlaylistUrl(modelJson.getString("hlsPreviewUrl"));
}
models.add(model);
}
return models;
}
public void setShowOnline(boolean online) { public void setShowOnline(boolean online) {
this.showOnline = online; this.showOnline = online;
} }

View File

@ -10,7 +10,7 @@ import ctbrec.ui.tabs.ThumbOverviewTab;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
public class Cam4TabProvider extends TabProvider { public class Cam4TabProvider implements TabProvider {
private Cam4 cam4; private Cam4 cam4;
private Recorder recorder; private Recorder recorder;
@ -44,8 +44,8 @@ public class Cam4TabProvider extends TabProvider {
} }
private Tab createTab(String name, String url) { private Tab createTab(String name, String url) {
Cam4UpdateService updateService = new Cam4UpdateService(url, false, cam4); var updateService = new Cam4UpdateService(url, false, cam4);
ThumbOverviewTab tab = new ThumbOverviewTab(name, updateService, cam4); var tab = new ThumbOverviewTab(name, updateService, cam4);
tab.setRecorder(recorder); tab.setRecorder(recorder);
return tab; return tab;
} }

View File

@ -13,7 +13,6 @@ import java.util.concurrent.Executors;
import org.json.JSONObject; import org.json.JSONObject;
import org.jsoup.nodes.Element; import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -28,7 +27,6 @@ import ctbrec.ui.SiteUiFactory;
import ctbrec.ui.tabs.PaginatedScheduledService; import ctbrec.ui.tabs.PaginatedScheduledService;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response;
public class Cam4UpdateService extends PaginatedScheduledService { public class Cam4UpdateService extends PaginatedScheduledService {
@ -43,7 +41,7 @@ public class Cam4UpdateService extends PaginatedScheduledService {
this.loginRequired = loginRequired; this.loginRequired = loginRequired;
ExecutorService executor = Executors.newSingleThreadExecutor(r -> { ExecutorService executor = Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r); var t = new Thread(r);
t.setDaemon(true); t.setDaemon(true);
t.setName("ThumbOverviewTab UpdateService"); t.setName("ThumbOverviewTab UpdateService");
return t; return t;
@ -64,35 +62,14 @@ public class Cam4UpdateService extends PaginatedScheduledService {
if (loginRequired) { if (loginRequired) {
SiteUiFactory.getUi(site).login(); SiteUiFactory.getUi(site).login();
} }
Request request = new Request.Builder() var request = new Request.Builder()
.url(pageUrl) .url(pageUrl)
.header(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage()) .header(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage())
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent) .header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.build(); .build();
try (Response response = site.getHttpClient().execute(request)) { try (var response = site.getHttpClient().execute(request)) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
JSONObject json = new JSONObject(response.body().string()); return parseModels(response.body().string());
String html = json.getString("html");
Elements profilesBoxes = HtmlParser.getTags(html, "div[class~=profileDataBox]");
List<Model> models = new ArrayList<>(profilesBoxes.size());
for (Element profileBox : profilesBoxes) {
String boxHtml = profileBox.html();
Element profileLink = HtmlParser.getTag(boxHtml, "a.profile-preview");
String path = profileLink.attr("href");
String slug = path.substring(1);
Cam4Model model = site.createModel(slug);
String playlistUrl = profileLink.attr("data-hls-preview-url");
model.setDisplayName(HtmlParser.getText(boxHtml, "div.profileBoxTitle a").trim());
model.setPlaylistUrl(playlistUrl);
model.setPreview("https://snapshots.xcdnpro.com/thumbnails/" + model.getName() + "?s=" + System.currentTimeMillis());
model.setDescription(parseDesription(boxHtml));
model.setOnlineState(ONLINE);
if (boxHtml.contains("In private show")) {
model.setOnlineState(PRIVATE);
}
models.add(model);
}
return models;
} else { } else {
throw new HttpException(response.code(), response.message()); throw new HttpException(response.code(), response.message());
} }
@ -100,17 +77,43 @@ public class Cam4UpdateService extends PaginatedScheduledService {
} }
} }
private String parseDesription(String boxHtml) {
try {
return HtmlParser.getText(boxHtml, "div[class~=statusMsg2]");
} catch(Exception e) {
LOG.trace("Couldn't parse description for room");
}
return "";
}
}; };
} }
private List<Model> parseModels(String body) {
var json = new JSONObject(body);
var html = json.getString("html");
var profilesBoxes = HtmlParser.getTags(html, "div[class~=profileDataBox]");
List<Model> models = new ArrayList<>(profilesBoxes.size());
for (Element profileBox : profilesBoxes) {
String boxHtml = profileBox.html();
Element profileLink = HtmlParser.getTag(boxHtml, "a.profile-preview");
String path = profileLink.attr("href");
var slug = path.substring(1);
Cam4Model model = site.createModel(slug);
String playlistUrl = profileLink.attr("data-hls-preview-url");
model.setDisplayName(HtmlParser.getText(boxHtml, "div.profileBoxTitle a").trim());
model.setPlaylistUrl(playlistUrl);
model.setPreview("https://snapshots.xcdnpro.com/thumbnails/" + model.getName() + "?s=" + System.currentTimeMillis());
model.setDescription(parseDesription(boxHtml));
model.setOnlineState(ONLINE);
if (boxHtml.contains("In private show")) {
model.setOnlineState(PRIVATE);
}
models.add(model);
}
return models;
}
private String parseDesription(String boxHtml) {
try {
return HtmlParser.getText(boxHtml, "div[class~=statusMsg2]");
} catch(Exception e) {
LOG.trace("Couldn't parse description for room");
}
return "";
}
public void setUrl(String url) { public void setUrl(String url) {
this.url = url; this.url = url;
} }

View File

@ -1,7 +1,6 @@
package ctbrec.ui.sites.camsoda; package ctbrec.ui.sites.camsoda;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.Settings;
import ctbrec.sites.camsoda.Camsoda; import ctbrec.sites.camsoda.Camsoda;
import ctbrec.ui.DesktopIntegration; import ctbrec.ui.DesktopIntegration;
import ctbrec.ui.settings.SettingsTab; import ctbrec.ui.settings.SettingsTab;
@ -25,15 +24,15 @@ public class CamsodaConfigUI extends AbstractConfigUI {
@Override @Override
public Parent createConfigPanel() { public Parent createConfigPanel() {
GridPane layout = SettingsTab.createGridLayout(); var layout = SettingsTab.createGridLayout();
Settings settings = Config.getInstance().getSettings(); var settings = Config.getInstance().getSettings();
int row = 0; var row = 0;
Label l = new Label("Active"); var l = new Label("Active");
layout.add(l, 0, row); layout.add(l, 0, row);
CheckBox enabled = new CheckBox(); var enabled = new CheckBox();
enabled.setSelected(!settings.disabledSites.contains(camsoda.getName())); enabled.setSelected(!settings.disabledSites.contains(camsoda.getName()));
enabled.setOnAction((e) -> { enabled.setOnAction(e -> {
if(enabled.isSelected()) { if(enabled.isSelected()) {
settings.disabledSites.remove(camsoda.getName()); settings.disabledSites.remove(camsoda.getName());
} else { } else {
@ -45,7 +44,7 @@ public class CamsodaConfigUI extends AbstractConfigUI {
layout.add(enabled, 1, row++); layout.add(enabled, 1, row++);
layout.add(new Label("CamSoda User"), 0, row); layout.add(new Label("CamSoda User"), 0, row);
TextField username = new TextField(Config.getInstance().getSettings().camsodaUsername); var username = new TextField(Config.getInstance().getSettings().camsodaUsername);
username.textProperty().addListener((ob, o, n) -> { username.textProperty().addListener((ob, o, n) -> {
if(!n.equals(Config.getInstance().getSettings().camsodaUsername)) { if(!n.equals(Config.getInstance().getSettings().camsodaUsername)) {
Config.getInstance().getSettings().camsodaUsername = username.getText(); Config.getInstance().getSettings().camsodaUsername = username.getText();
@ -59,7 +58,7 @@ public class CamsodaConfigUI extends AbstractConfigUI {
layout.add(username, 1, row++); layout.add(username, 1, row++);
layout.add(new Label("CamSoda Password"), 0, row); layout.add(new Label("CamSoda Password"), 0, row);
PasswordField password = new PasswordField(); var password = new PasswordField();
password.setText(Config.getInstance().getSettings().camsodaPassword); password.setText(Config.getInstance().getSettings().camsodaPassword);
password.textProperty().addListener((ob, o, n) -> { password.textProperty().addListener((ob, o, n) -> {
if(!n.equals(Config.getInstance().getSettings().camsodaPassword)) { if(!n.equals(Config.getInstance().getSettings().camsodaPassword)) {
@ -73,9 +72,9 @@ public class CamsodaConfigUI extends AbstractConfigUI {
GridPane.setColumnSpan(password, 2); GridPane.setColumnSpan(password, 2);
layout.add(password, 1, row++); layout.add(password, 1, row++);
Button createAccount = new Button("Create new Account"); var createAccount = new Button("Create new Account");
createAccount.setOnAction((e) -> DesktopIntegration.open(camsoda.getAffiliateLink())); createAccount.setOnAction(e -> DesktopIntegration.open(camsoda.getAffiliateLink()));
layout.add(createAccount, 1, row++); layout.add(createAccount, 1, row);
GridPane.setColumnSpan(createAccount, 2); GridPane.setColumnSpan(createAccount, 2);
GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN)); GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN)); GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));

View File

@ -34,10 +34,10 @@ public class CamsodaFollowedTab extends ThumbOverviewTab implements FollowedTab
} }
private void addOnlineOfflineSelector() { private void addOnlineOfflineSelector() {
ToggleGroup group = new ToggleGroup(); var group = new ToggleGroup();
RadioButton online = new RadioButton("online"); var online = new RadioButton("online");
online.setToggleGroup(group); online.setToggleGroup(group);
RadioButton offline = new RadioButton("offline"); var offline = new RadioButton("offline");
offline.setToggleGroup(group); offline.setToggleGroup(group);
pagination.getChildren().add(online); pagination.getChildren().add(online);
pagination.getChildren().add(offline); pagination.getChildren().add(offline);
@ -59,7 +59,7 @@ public class CamsodaFollowedTab extends ThumbOverviewTab implements FollowedTab
@Override @Override
protected void onFail(WorkerStateEvent event) { protected void onFail(WorkerStateEvent event) {
String msg = ""; var msg = "";
if (event.getSource().getException() != null) { if (event.getSource().getException() != null) {
msg = ": " + event.getSource().getException().getMessage(); msg = ": " + event.getSource().getException().getMessage();
} }
@ -75,10 +75,8 @@ public class CamsodaFollowedTab extends ThumbOverviewTab implements FollowedTab
public void setScene(Scene scene) { public void setScene(Scene scene) {
scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> { scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if (this.isSelected()) { if (this.isSelected() && event.getCode() == KeyCode.DELETE) {
if (event.getCode() == KeyCode.DELETE) { follow(selectedThumbCells, false);
follow(selectedThumbCells, false);
}
} }
}); });
} }

View File

@ -8,13 +8,12 @@ import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle; import java.time.format.FormatStyle;
import java.time.temporal.TemporalAccessor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -69,7 +68,7 @@ public class CamsodaShowsTab extends Tab implements TabSelectionListener {
showList.setPadding(new Insets(5)); showList.setPadding(new Insets(5));
showList.setHgap(5); showList.setHgap(5);
showList.setVgap(5); showList.setVgap(5);
ProgressIndicator progressIndicator = new ProgressIndicator(); var progressIndicator = new ProgressIndicator();
progressIndicator.setPrefSize(100, 100); progressIndicator.setPrefSize(100, 100);
setContent(progressIndicator); setContent(progressIndicator);
setClosable(false); setClosable(false);
@ -81,41 +80,7 @@ public class CamsodaShowsTab extends Tab implements TabSelectionListener {
Task<List<ShowBox>> task = new Task<List<ShowBox>>() { Task<List<ShowBox>> task = new Task<List<ShowBox>>() {
@Override @Override
protected List<ShowBox> call() throws Exception { protected List<ShowBox> call() throws Exception {
String url = camsoda.getBaseUrl() + "/api/v1/user/model_shows"; return loadShows();
Request req = new Request.Builder().url(url).build();
try(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);
showErrorDialog("Oh no!", "Couldn't load upcoming CamSoda shows", "Got an unexpected response from server");
}
} else {
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 @Override
@ -125,11 +90,14 @@ public class CamsodaShowsTab extends Tab implements TabSelectionListener {
try { try {
List<ShowBox> boxes = get(); List<ShowBox> boxes = get();
showList.getChildren().clear(); showList.getChildren().clear();
int index = 0; var index = 0;
for (ShowBox showBox : boxes) { for (ShowBox showBox : boxes) {
showList.add(showBox, index % 2, index++ / 2); showList.add(showBox, index % 2, index++ / 2);
GridPane.setMargin(showBox, new Insets(20, 20, 0, 20)); GridPane.setMargin(showBox, new Insets(20, 20, 0, 20));
} }
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
LOG.error("Couldn't load upcoming camsoda shows", e);
} catch (Exception e) { } catch (Exception e) {
LOG.error("Couldn't load upcoming camsoda shows", e); LOG.error("Couldn't load upcoming camsoda shows", e);
} }
@ -140,6 +108,44 @@ public class CamsodaShowsTab extends Tab implements TabSelectionListener {
GlobalThreadPool.submit(task); GlobalThreadPool.submit(task);
} }
private List<ShowBox> loadShows() throws IOException {
String url = camsoda.getBaseUrl() + "/api/v1/user/model_shows";
Request req = new Request.Builder().url(url).build();
try(var response = camsoda.getHttpClient().execute(req)) {
if (response.isSuccessful()) {
var json = new JSONObject(response.body().string());
if (json.optInt("success") == 1) {
List<ShowBox> boxes = new ArrayList<>();
var results = json.getJSONArray("results");
for (var i = 0; i < results.length(); i++) {
var result = results.getJSONObject(i);
var modelUrl = camsoda.getBaseUrl() + result.getString("url");
var name = modelUrl.substring(modelUrl.lastIndexOf('/') + 1);
var 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);
showErrorDialog("Oh no!", "Couldn't load upcoming CamSoda shows", "Got an unexpected response from server");
}
} else {
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) {
var formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
var ta = formatter.parse(string.replace(" UTC", ""));
var instant = Instant.from(ta);
return ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
}
@Override @Override
public void deselected() { public void deselected() {
// nothing to do // nothing to do
@ -165,31 +171,31 @@ public class CamsodaShowsTab extends Tab implements TabSelectionListener {
setPrefHeight(268); setPrefHeight(268);
setContent(root); setContent(root);
ImageView thumb = new ImageView(); var thumb = new ImageView();
thumb.setPreserveRatio(true); thumb.setPreserveRatio(true);
thumb.setFitHeight(thumbSize); thumb.setFitHeight(thumbSize);
loadImage(model, thumb); loadImage(model, thumb);
root.setLeft(new ProgressIndicator()); root.setLeft(new ProgressIndicator());
BorderPane.setMargin(thumb, new Insets(10, 30, 10, 10)); BorderPane.setMargin(thumb, new Insets(10, 30, 10, 10));
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.MEDIUM); var formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.MEDIUM);
GridPane grid = new GridPane(); var grid = new GridPane();
grid.add(createLabel("Start", true), 0, 0); grid.add(createLabel("Start", true), 0, 0);
grid.add(createLabel(formatter.format(startTime), false), 1, 0); grid.add(createLabel(formatter.format(startTime), false), 1, 0);
grid.add(createLabel("End", true), 0, 1); grid.add(createLabel("End", true), 0, 1);
grid.add(createLabel(formatter.format(endTime), false), 1, 1); grid.add(createLabel(formatter.format(endTime), false), 1, 1);
Button record = new Button("Record Model"); var recordButton = new Button("Record Model");
record.setTooltip(new Tooltip(record.getText())); recordButton.setTooltip(new Tooltip(recordButton.getText()));
record.setOnAction(evt -> record(model)); recordButton.setOnAction(evt -> recordModel(model));
grid.add(record, 1, 2); grid.add(recordButton, 1, 2);
GridPane.setMargin(record, new Insets(10)); GridPane.setMargin(recordButton, new Insets(10));
Button follow = new Button("Follow"); var follow = new Button("Follow");
follow.setTooltip(new Tooltip(follow.getText())); follow.setTooltip(new Tooltip(follow.getText()));
follow.setOnAction(evt -> follow(model)); follow.setOnAction(evt -> follow(model));
grid.add(follow, 1, 3); grid.add(follow, 1, 3);
GridPane.setMargin(follow, new Insets(10)); GridPane.setMargin(follow, new Insets(10));
Button openInBrowser = new Button("Open in Browser"); var openInBrowser = new Button("Open in Browser");
openInBrowser.setTooltip(new Tooltip(openInBrowser.getText())); openInBrowser.setTooltip(new Tooltip(openInBrowser.getText()));
openInBrowser.setOnAction(evt -> DesktopIntegration.open(model.getUrl())); openInBrowser.setOnAction(evt -> DesktopIntegration.open(model.getUrl()));
grid.add(openInBrowser, 1, 4); grid.add(openInBrowser, 1, 4);
@ -197,7 +203,7 @@ public class CamsodaShowsTab extends Tab implements TabSelectionListener {
root.setCenter(grid); root.setCenter(grid);
loadImage(model, thumb); loadImage(model, thumb);
record.minWidthProperty().bind(openInBrowser.widthProperty()); recordButton.minWidthProperty().bind(openInBrowser.widthProperty());
follow.minWidthProperty().bind(openInBrowser.widthProperty()); follow.minWidthProperty().bind(openInBrowser.widthProperty());
} }
@ -216,7 +222,7 @@ public class CamsodaShowsTab extends Tab implements TabSelectionListener {
}); });
} }
private void record(Model model) { private void recordModel(Model model) {
setCursor(Cursor.WAIT); setCursor(Cursor.WAIT);
GlobalThreadPool.submit(() -> { GlobalThreadPool.submit(() -> {
try { try {
@ -233,47 +239,56 @@ public class CamsodaShowsTab extends Tab implements TabSelectionListener {
GlobalThreadPool.submit(() -> { GlobalThreadPool.submit(() -> {
try { try {
String url = camsoda.getBaseUrl() + "/api/v1/user/" + model.getName(); String url = camsoda.getBaseUrl() + "/api/v1/user/" + model.getName();
Request detailRequest = new Request.Builder().url(url).build(); var detailRequest = new Request.Builder().url(url).build();
Response resp = camsoda.getHttpClient().execute(detailRequest); try (Response resp = camsoda.getHttpClient().execute(detailRequest)) {
if (resp.isSuccessful()) { if (resp.isSuccessful()) {
JSONObject json = new JSONObject(resp.body().string()); parseImageUrl(resp.body().string()).ifPresent(imageUrl -> updateImageView(thumb, imageUrl));
if (json.optBoolean("status") && json.has("user")) {
JSONObject user = json.getJSONObject("user");
if (user.has("settings")) {
JSONObject settings = user.getJSONObject("settings");
String imageUrl;
if(Objects.equals(System.getenv("CTBREC_DEV"), "1")) {
imageUrl = getClass().getResource("/image_not_found.png").toString();
} else {
if (settings.has("offline_picture")) {
imageUrl = settings.getString("offline_picture");
} else {
imageUrl = "https:" + user.getString("thumb");
}
}
Platform.runLater(() -> {
Image img = new Image(imageUrl, 1000, thumbSize, true, true, true);
img.progressProperty().addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> {
if (newValue.doubleValue() == 1.0) {
thumb.setImage(img);
root.setLeft(thumb);
}
});
});
}
} }
} }
resp.close();
} catch (Exception e) { } catch (Exception e) {
LOG.error("Couldn't load model details", e); LOG.error("Couldn't load model details", e);
} }
}); });
} }
private void updateImageView(ImageView view, String imageUrl) {
Platform.runLater(() -> {
var img = new Image(imageUrl, 1000, thumbSize, true, true, true);
img.progressProperty().addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> {
if (newValue.doubleValue() == 1.0) {
view.setImage(img);
root.setLeft(view);
}
});
});
}
private Optional<String> parseImageUrl(String body) {
var json = new JSONObject(body);
if (json.optBoolean("status") && json.has("user")) {
var user = json.getJSONObject("user");
if (user.has("settings")) {
var settings = user.getJSONObject("settings");
String imageUrl;
if (Objects.equals(System.getenv("CTBREC_DEV"), "1")) {
imageUrl = getClass().getResource("/image_not_found.png").toString();
} else {
if (settings.has("offline_picture")) {
imageUrl = settings.getString("offline_picture");
} else {
imageUrl = "https:" + user.getString("thumb");
}
}
return Optional.of(imageUrl);
}
}
return Optional.empty();
}
private Node createLabel(String string, boolean bold) { private Node createLabel(String string, boolean bold) {
Label label = new Label(string); var label = new Label(string);
label.setPadding(new Insets(10)); label.setPadding(new Insets(10));
Font def = Font.getDefault(); var def = Font.getDefault();
label.setFont(Font.font(def.getFamily(), bold ? FontWeight.BOLD : FontWeight.NORMAL, 16)); label.setFont(Font.font(def.getFamily(), bold ? FontWeight.BOLD : FontWeight.NORMAL, 16));
return label; return label;
} }

View File

@ -34,58 +34,4 @@ public class CamsodaSiteUi extends AbstractSiteUi {
boolean automaticLogin = camsoda.login(); boolean automaticLogin = camsoda.login();
return automaticLogin; return automaticLogin;
} }
// @SuppressWarnings("unused")
// private boolean loginWithDialog() throws IOException {
// BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
//
// Runnable showDialog = () -> {
// // login with external browser
// CamsodaLoginDialog loginDialog = new CamsodaLoginDialog();
//
// // transfer cookies from WebView to OkHttp cookie jar
// transferCookies(loginDialog);
//
// try {
// queue.put(true);
// } catch (InterruptedException e) {
// LOG.error("Error while signaling termination", e);
// }
// };
//
// if(Platform.isFxApplicationThread()) {
// showDialog.run();
// } else {
// Platform.runLater(showDialog);
// try {
// queue.take();
// } catch (InterruptedException e) {
// LOG.error("Error while waiting for login dialog to close", e);
// throw new IOException(e);
// }
// }
//
// CamsodaHttpClient httpClient = (CamsodaHttpClient)camsoda.getHttpClient();
// boolean loggedIn = httpClient.checkLoginSuccess();
// return loggedIn;
// }
//
// private void transferCookies(CamsodaLoginDialog loginDialog) {
// HttpUrl redirectedUrl = HttpUrl.parse(loginDialog.getUrl());
// List<Cookie> cookies = new ArrayList<>();
// for (HttpCookie webViewCookie : loginDialog.getCookies()) {
// Cookie cookie = Cookie.parse(redirectedUrl, webViewCookie.toString());
// cookies.add(cookie);
// }
// camsoda.getHttpClient().getCookieJar().saveFromResponse(redirectedUrl, cookies);
//
// HttpUrl origUrl = HttpUrl.parse(Camsoda.BASE_URI);
// cookies = new ArrayList<>();
// for (HttpCookie webViewCookie : loginDialog.getCookies()) {
// Cookie cookie = Cookie.parse(origUrl, webViewCookie.toString());
// cookies.add(cookie);
// }
// camsoda.getHttpClient().getCookieJar().saveFromResponse(origUrl, cookies);
// }
} }

View File

@ -15,7 +15,7 @@ import ctbrec.ui.tabs.ThumbOverviewTab;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
public class CamsodaTabProvider extends TabProvider { public class CamsodaTabProvider implements TabProvider {
private static final String API_URL = BASE_URI + "/api/v1/browse/online"; private static final String API_URL = BASE_URI + "/api/v1/browse/online";
private Camsoda camsoda; private Camsoda camsoda;
@ -37,7 +37,6 @@ public class CamsodaTabProvider extends TabProvider {
tabs.add(createTab("Male", API_URL, m -> Objects.equals("m", m.getGender()))); tabs.add(createTab("Male", API_URL, m -> Objects.equals("m", m.getGender())));
tabs.add(createTab("Couples", API_URL, m -> Objects.equals("c", m.getGender()))); tabs.add(createTab("Couples", API_URL, m -> Objects.equals("c", m.getGender())));
tabs.add(createTab("Trans", API_URL, m -> Objects.equals("t", m.getGender()))); tabs.add(createTab("Trans", API_URL, m -> Objects.equals("t", m.getGender())));
//tabs.add(createTab("#petite", BASE_URI + "/api/v1/browse/tag-petite", m -> true));
followedTab.setRecorder(recorder); followedTab.setRecorder(recorder);
followedTab.setScene(scene); followedTab.setScene(scene);
tabs.add(followedTab); tabs.add(followedTab);
@ -51,8 +50,8 @@ public class CamsodaTabProvider extends TabProvider {
} }
private Tab createTab(String title, String url, Predicate<CamsodaModel> filter) { private Tab createTab(String title, String url, Predicate<CamsodaModel> filter) {
CamsodaUpdateService updateService = new CamsodaUpdateService(url, false, camsoda, filter); var updateService = new CamsodaUpdateService(url, false, camsoda, filter);
ThumbOverviewTab tab = new ThumbOverviewTab(title, updateService, camsoda); var tab = new ThumbOverviewTab(title, updateService, camsoda);
tab.setRecorder(recorder); tab.setRecorder(recorder);
return tab; return tab;
} }

View File

@ -25,7 +25,6 @@ import ctbrec.ui.SiteUiFactory;
import ctbrec.ui.tabs.PaginatedScheduledService; import ctbrec.ui.tabs.PaginatedScheduledService;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response;
public class CamsodaUpdateService extends PaginatedScheduledService { public class CamsodaUpdateService extends PaginatedScheduledService {
@ -53,7 +52,7 @@ public class CamsodaUpdateService extends PaginatedScheduledService {
return loadOnlineModels().stream() return loadOnlineModels().stream()
.sorted((m1,m2) -> (int)(m2.getSortOrder() - m1.getSortOrder())) .sorted((m1,m2) -> (int)(m2.getSortOrder() - m1.getSortOrder()))
.filter(filter) .filter(filter)
.skip( (page-1) * modelsPerPage) .skip( (page-1) * (long)modelsPerPage)
.limit(modelsPerPage) .limit(modelsPerPage)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
@ -61,71 +60,17 @@ public class CamsodaUpdateService extends PaginatedScheduledService {
} }
protected List<CamsodaModel> loadOnlineModels() throws IOException { protected List<CamsodaModel> loadOnlineModels() throws IOException {
List<CamsodaModel> models = new ArrayList<>(); if (loginRequired && StringUtil.isBlank(ctbrec.Config.getInstance().getSettings().camsodaUsername)) {
if(loginRequired && StringUtil.isBlank(ctbrec.Config.getInstance().getSettings().camsodaUsername)) {
return Collections.emptyList(); return Collections.emptyList();
} else { } else {
LOG.debug("Fetching page {}", url); LOG.debug("Fetching page {}", url);
if(loginRequired) { if (loginRequired) {
SiteUiFactory.getUi(camsoda).login(); SiteUiFactory.getUi(camsoda).login();
} }
Request request = new Request.Builder().url(url).build(); var request = new Request.Builder().url(url).build();
try (Response response = camsoda.getHttpClient().execute(request)) { try (var response = camsoda.getHttpClient().execute(request)) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
String body = response.body().string(); return parseModels(response.body().string());
JSONObject json = new JSONObject(body);
JSONArray template = json.getJSONArray("template");
JSONArray results = json.getJSONArray("results");
for (int i = 0; i < results.length(); i++) {
JSONObject result = results.getJSONObject(i);
Object templateObject = result.get("tpl");
CamsodaModel model;
try {
if (templateObject instanceof JSONObject) {
JSONObject tpl = (JSONObject) templateObject;
String name = tpl.getString(Integer.toString(getTemplateIndex(template, "username")));
model = (CamsodaModel) camsoda.createModel(name);
model.setDescription(tpl.getString(Integer.toString(getTemplateIndex(template, "subject_html"))));
model.setSortOrder(tpl.getFloat(Integer.toString(getTemplateIndex(template, "sort_value"))));
model.setNew(result.optBoolean("new"));
model.setGender(tpl.getString(Integer.toString(getTemplateIndex(template, "gender"))));
String preview = "https:" + tpl.getString(Integer.toString(getTemplateIndex(template, "thumb")));
model.setPreview(preview);
String displayName = tpl.getString(Integer.toString(getTemplateIndex(template, "display_name")));
model.setDisplayName(displayName.replaceAll("[^a-zA-Z0-9]", ""));
if (model.getDisplayName().isBlank()) {
model.setDisplayName(name);
}
model.setOnlineState(tpl.getString(Integer.toString(getTemplateIndex(template, "stream_name"))).isEmpty() ? OFFLINE : ONLINE);
try {
String statusIndex = Integer.toString(getTemplateIndex(template, "status"));
if (tpl.has(statusIndex)) {
model.setOnlineStateByStatus(tpl.getString(statusIndex));
}
} catch (NoSuchElementException e) {
}
models.add(model);
} else if (templateObject instanceof JSONArray) {
JSONArray tpl = (JSONArray) templateObject;
String name = tpl.getString(getTemplateIndex(template, "username"));
model = (CamsodaModel) camsoda.createModel(name);
model.setSortOrder(tpl.getFloat(getTemplateIndex(template, "sort_value")));
model.setDescription(tpl.getString(getTemplateIndex(template, "subject_html")));
String preview = "https:" + tpl.getString(getTemplateIndex(template, "thumb"));
model.setPreview(preview);
model.setOnlineStateByStatus(tpl.getString(getTemplateIndex(template, "status")));
String displayName = tpl.getString(getTemplateIndex(template, "display_name"));
model.setDisplayName(displayName.replaceAll("[^a-zA-Z0-9]", ""));
if (model.getDisplayName().isBlank()) {
model.setDisplayName(name);
}
models.add(model);
}
} catch (Exception e) {
LOG.warn("Couldn't parse one of the models: {}", result, e);
}
}
return models;
} else { } else {
throw new HttpException(response.code(), response.message()); throw new HttpException(response.code(), response.message());
} }
@ -133,10 +78,79 @@ public class CamsodaUpdateService extends PaginatedScheduledService {
} }
} }
private List<CamsodaModel> parseModels(String body) {
List<CamsodaModel> models = new ArrayList<>();
var json = new JSONObject(body);
var template = json.getJSONArray("template");
var results = json.getJSONArray("results");
for (var i = 0; i < results.length(); i++) {
var result = results.getJSONObject(i);
var templateObject = result.get("tpl");
try {
if (templateObject instanceof JSONObject) {
parseModelFromObject(result, templateObject, template, models);
} else if (templateObject instanceof JSONArray) {
parseModelFromArray(templateObject, template, models);
}
} catch (Exception e) {
LOG.warn("Couldn't parse one of the models: {}", result, e);
}
}
return models;
}
private void parseModelFromArray(Object templateObject, JSONArray template, List<CamsodaModel> models) {
var tpl = (JSONArray) templateObject;
var name = tpl.getString(getTemplateIndex(template, "username"));
CamsodaModel model = (CamsodaModel) camsoda.createModel(name);
model.setSortOrder(tpl.getFloat(getTemplateIndex(template, "sort_value")));
model.setDescription(tpl.getString(getTemplateIndex(template, "subject_html")));
var preview = "https:" + tpl.getString(getTemplateIndex(template, "thumb"));
model.setPreview(preview);
model.setOnlineStateByStatus(tpl.getString(getTemplateIndex(template, "status")));
var displayName = tpl.getString(getTemplateIndex(template, "display_name"));
model.setDisplayName(displayName.replaceAll("[^a-zA-Z0-9]", ""));
if (model.getDisplayName().isBlank()) {
model.setDisplayName(name);
}
models.add(model);
}
private void parseModelFromObject(JSONObject result, Object templateObject, JSONArray template, List<CamsodaModel> models) {
var tpl = (JSONObject) templateObject;
var name = tpl.getString(Integer.toString(getTemplateIndex(template, "username")));
CamsodaModel model = (CamsodaModel) camsoda.createModel(name);
model.setDescription(tpl.getString(Integer.toString(getTemplateIndex(template, "subject_html"))));
model.setSortOrder(tpl.getFloat(Integer.toString(getTemplateIndex(template, "sort_value"))));
model.setNew(result.optBoolean("new"));
model.setGender(tpl.getString(Integer.toString(getTemplateIndex(template, "gender"))));
var preview = "https:" + tpl.getString(Integer.toString(getTemplateIndex(template, "thumb")));
model.setPreview(preview);
var displayName = tpl.getString(Integer.toString(getTemplateIndex(template, "display_name")));
model.setDisplayName(displayName.replaceAll("[^a-zA-Z0-9]", ""));
if (model.getDisplayName().isBlank()) {
model.setDisplayName(name);
}
model.setOnlineState(tpl.getString(Integer.toString(getTemplateIndex(template, "stream_name"))).isEmpty() ? OFFLINE : ONLINE);
parseStatus(template, tpl, model);
models.add(model);
}
private void parseStatus(JSONArray template, JSONObject tpl, CamsodaModel model) {
try {
var statusIndex = Integer.toString(getTemplateIndex(template, "status"));
if (tpl.has(statusIndex)) {
model.setOnlineStateByStatus(tpl.getString(statusIndex));
}
} catch (NoSuchElementException e) {
// that's ok
}
}
private int getTemplateIndex(JSONArray template, String string) { private int getTemplateIndex(JSONArray template, String string) {
for (int i = 0; i < template.length(); i++) { for (var i = 0; i < template.length(); i++) {
String s = template.getString(i); var s = template.getString(i);
if(Objects.equals(s, string)) { if (Objects.equals(s, string)) {
return i; return i;
} }
} }

View File

@ -1,7 +1,6 @@
package ctbrec.ui.sites.chaturbate; package ctbrec.ui.sites.chaturbate;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.Settings;
import ctbrec.sites.chaturbate.Chaturbate; import ctbrec.sites.chaturbate.Chaturbate;
import ctbrec.ui.DesktopIntegration; import ctbrec.ui.DesktopIntegration;
import ctbrec.ui.settings.SettingsTab; import ctbrec.ui.settings.SettingsTab;
@ -25,15 +24,15 @@ public class ChaturbateConfigUi extends AbstractConfigUI {
@Override @Override
public Parent createConfigPanel() { public Parent createConfigPanel() {
Settings settings = Config.getInstance().getSettings(); var settings = Config.getInstance().getSettings();
GridPane layout = SettingsTab.createGridLayout(); GridPane layout = SettingsTab.createGridLayout();
int row = 0; var row = 0;
Label l = new Label("Active"); var l = new Label("Active");
layout.add(l, 0, row); layout.add(l, 0, row);
CheckBox enabled = new CheckBox(); var enabled = new CheckBox();
enabled.setSelected(!settings.disabledSites.contains(chaturbate.getName())); enabled.setSelected(!settings.disabledSites.contains(chaturbate.getName()));
enabled.setOnAction((e) -> { enabled.setOnAction(e -> {
if(enabled.isSelected()) { if(enabled.isSelected()) {
settings.disabledSites.remove(chaturbate.getName()); settings.disabledSites.remove(chaturbate.getName());
} else { } else {
@ -45,7 +44,7 @@ public class ChaturbateConfigUi extends AbstractConfigUI {
layout.add(enabled, 1, row++); layout.add(enabled, 1, row++);
layout.add(new Label("Chaturbate User"), 0, row); layout.add(new Label("Chaturbate User"), 0, row);
TextField username = new TextField(Config.getInstance().getSettings().chaturbateUsername); var username = new TextField(Config.getInstance().getSettings().chaturbateUsername);
username.textProperty().addListener((ob, o, n) -> { username.textProperty().addListener((ob, o, n) -> {
if(!n.equals(Config.getInstance().getSettings().chaturbateUsername)) { if(!n.equals(Config.getInstance().getSettings().chaturbateUsername)) {
Config.getInstance().getSettings().chaturbateUsername = n; Config.getInstance().getSettings().chaturbateUsername = n;
@ -59,7 +58,7 @@ public class ChaturbateConfigUi extends AbstractConfigUI {
layout.add(username, 1, row++); layout.add(username, 1, row++);
layout.add(new Label("Chaturbate Password"), 0, row); layout.add(new Label("Chaturbate Password"), 0, row);
PasswordField password = new PasswordField(); var password = new PasswordField();
password.setText(Config.getInstance().getSettings().chaturbatePassword); password.setText(Config.getInstance().getSettings().chaturbatePassword);
password.textProperty().addListener((ob, o, n) -> { password.textProperty().addListener((ob, o, n) -> {
if(!n.equals(Config.getInstance().getSettings().chaturbatePassword)) { if(!n.equals(Config.getInstance().getSettings().chaturbatePassword)) {
@ -74,7 +73,7 @@ public class ChaturbateConfigUi extends AbstractConfigUI {
layout.add(password, 1, row++); layout.add(password, 1, row++);
layout.add(new Label("Chaturbate Base URL"), 0, row); layout.add(new Label("Chaturbate Base URL"), 0, row);
TextField baseUrl = new TextField(); var baseUrl = new TextField();
baseUrl.setText(Config.getInstance().getSettings().chaturbateBaseUrl); baseUrl.setText(Config.getInstance().getSettings().chaturbateBaseUrl);
baseUrl.textProperty().addListener((ob, o, n) -> { baseUrl.textProperty().addListener((ob, o, n) -> {
Config.getInstance().getSettings().chaturbateBaseUrl = baseUrl.getText(); Config.getInstance().getSettings().chaturbateBaseUrl = baseUrl.getText();
@ -85,9 +84,9 @@ public class ChaturbateConfigUi extends AbstractConfigUI {
GridPane.setColumnSpan(baseUrl, 2); GridPane.setColumnSpan(baseUrl, 2);
layout.add(baseUrl, 1, row++); layout.add(baseUrl, 1, row++);
Button createAccount = new Button("Create new Account"); var createAccount = new Button("Create new Account");
createAccount.setOnAction((e) -> DesktopIntegration.open(Chaturbate.REGISTRATION_LINK)); createAccount.setOnAction(e -> DesktopIntegration.open(Chaturbate.REGISTRATION_LINK));
layout.add(createAccount, 1, row++); layout.add(createAccount, 1, row);
GridPane.setColumnSpan(createAccount, 2); GridPane.setColumnSpan(createAccount, 2);
GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN)); GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN)); GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));

View File

@ -34,17 +34,17 @@ public class ChaturbateFollowedTab extends ThumbOverviewTab implements FollowedT
} }
private void addOnlineOfflineSelector() { private void addOnlineOfflineSelector() {
ToggleGroup group = new ToggleGroup(); var group = new ToggleGroup();
RadioButton online = new RadioButton("online"); var online = new RadioButton("online");
online.setToggleGroup(group); online.setToggleGroup(group);
RadioButton offline = new RadioButton("offline"); var offline = new RadioButton("offline");
offline.setToggleGroup(group); offline.setToggleGroup(group);
pagination.getChildren().add(online); pagination.getChildren().add(online);
pagination.getChildren().add(offline); pagination.getChildren().add(offline);
HBox.setMargin(online, new Insets(5,5,5,40)); HBox.setMargin(online, new Insets(5,5,5,40));
HBox.setMargin(offline, new Insets(5,5,5,5)); HBox.setMargin(offline, new Insets(5,5,5,5));
online.setSelected(true); online.setSelected(true);
group.selectedToggleProperty().addListener((e) -> { group.selectedToggleProperty().addListener(e -> {
if(online.isSelected()) { if(online.isSelected()) {
((ChaturbateUpdateService)updateService).setUrl(onlineUrl); ((ChaturbateUpdateService)updateService).setUrl(onlineUrl);
} else { } else {
@ -75,10 +75,8 @@ public class ChaturbateFollowedTab extends ThumbOverviewTab implements FollowedT
public void setScene(Scene scene) { public void setScene(Scene scene) {
scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> { scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if(this.isSelected()) { if (this.isSelected() && event.getCode() == KeyCode.DELETE) {
if(event.getCode() == KeyCode.DELETE) { follow(selectedThumbCells, false);
follow(selectedThumbCells, false);
}
} }
}); });
} }

View File

@ -10,7 +10,7 @@ import ctbrec.ui.tabs.ThumbOverviewTab;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
public class ChaturbateTabProvider extends TabProvider { public class ChaturbateTabProvider implements TabProvider {
private Chaturbate chaturbate; private Chaturbate chaturbate;
private Recorder recorder; private Recorder recorder;
@ -44,8 +44,8 @@ public class ChaturbateTabProvider extends TabProvider {
} }
private Tab createTab(String title, String url) { private Tab createTab(String title, String url) {
ChaturbateUpdateService updateService = new ChaturbateUpdateService(url, false, chaturbate); var updateService = new ChaturbateUpdateService(url, false, chaturbate);
ThumbOverviewTab tab = new ThumbOverviewTab(title, updateService, chaturbate); var tab = new ThumbOverviewTab(title, updateService, chaturbate);
tab.setRecorder(recorder); tab.setRecorder(recorder);
tab.setImageAspectRatio(9.0 / 16.0); tab.setImageAspectRatio(9.0 / 16.0);
return tab; return tab;

View File

@ -16,7 +16,6 @@ import ctbrec.ui.SiteUiFactory;
import ctbrec.ui.tabs.PaginatedScheduledService; import ctbrec.ui.tabs.PaginatedScheduledService;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response;
public class ChaturbateUpdateService extends PaginatedScheduledService { public class ChaturbateUpdateService extends PaginatedScheduledService {
@ -31,7 +30,7 @@ public class ChaturbateUpdateService extends PaginatedScheduledService {
this.chaturbate = chaturbate; this.chaturbate = chaturbate;
ExecutorService executor = Executors.newSingleThreadExecutor(r -> { ExecutorService executor = Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r); var t = new Thread(r);
t.setDaemon(true); t.setDaemon(true);
t.setName("ThumbOverviewTab UpdateService"); t.setName("ThumbOverviewTab UpdateService");
return t; return t;
@ -44,7 +43,7 @@ public class ChaturbateUpdateService extends PaginatedScheduledService {
return new Task<List<Model>>() { return new Task<List<Model>>() {
@Override @Override
public List<Model> call() throws IOException { public List<Model> call() throws IOException {
if(loginRequired && !chaturbate.credentialsAvailable()) { if (loginRequired && !chaturbate.credentialsAvailable()) {
return Collections.emptyList(); return Collections.emptyList();
} else { } else {
String pageUrl = ChaturbateUpdateService.this.url + "?page="+page+"&keywords=&_=" + System.currentTimeMillis(); String pageUrl = ChaturbateUpdateService.this.url + "?page="+page+"&keywords=&_=" + System.currentTimeMillis();
@ -52,16 +51,15 @@ public class ChaturbateUpdateService extends PaginatedScheduledService {
if(loginRequired) { if(loginRequired) {
SiteUiFactory.getUi(chaturbate).login(); SiteUiFactory.getUi(chaturbate).login();
} }
Request request = new Request.Builder().url(pageUrl).build(); var request = new Request.Builder().url(pageUrl).build();
Response response = chaturbate.getHttpClient().execute(request); try (var response = chaturbate.getHttpClient().execute(request)) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
List<Model> models = ChaturbateModelParser.parseModels(chaturbate, response.body().string()); List<Model> models = ChaturbateModelParser.parseModels(chaturbate, response.body().string());
response.close(); return models;
return models; } else {
} else { int code = response.code();
int code = response.code(); throw new IOException("HTTP status " + code);
response.close(); }
throw new IOException("HTTP status " + code);
} }
} }
} }

View File

@ -14,25 +14,19 @@ public class Fc2FollowedTab extends ThumbOverviewTab implements FollowedTab {
super("Followed", new Fc2FollowedUpdateService(fc2live), fc2live); super("Followed", new Fc2FollowedUpdateService(fc2live), fc2live);
} }
@Override
protected void createGui() {
super.createGui();
//addOnlineOfflineSelector();
}
@SuppressWarnings("unused") @SuppressWarnings("unused")
private void addOnlineOfflineSelector() { private void addOnlineOfflineSelector() {
ToggleGroup group = new ToggleGroup(); var group = new ToggleGroup();
RadioButton online = new RadioButton("online"); var online = new RadioButton("online");
online.setToggleGroup(group); online.setToggleGroup(group);
RadioButton offline = new RadioButton("offline"); var offline = new RadioButton("offline");
offline.setToggleGroup(group); offline.setToggleGroup(group);
pagination.getChildren().add(online); pagination.getChildren().add(online);
pagination.getChildren().add(offline); pagination.getChildren().add(offline);
HBox.setMargin(online, new Insets(5,5,5,40)); HBox.setMargin(online, new Insets(5,5,5,40));
HBox.setMargin(offline, new Insets(5,5,5,5)); HBox.setMargin(offline, new Insets(5,5,5,5));
online.setSelected(true); online.setSelected(true);
group.selectedToggleProperty().addListener((e) -> { group.selectedToggleProperty().addListener(e -> {
((Fc2FollowedUpdateService)updateService).setShowOnline(online.isSelected()); ((Fc2FollowedUpdateService)updateService).setShowOnline(online.isSelected());
queue.clear(); queue.clear();
updateService.restart(); updateService.restart();

View File

@ -6,7 +6,6 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import ctbrec.Config; import ctbrec.Config;
@ -34,54 +33,58 @@ public class Fc2FollowedUpdateService extends PaginatedScheduledService {
return new Task<List<Model>>() { return new Task<List<Model>>() {
@Override @Override
public List<Model> call() throws IOException { public List<Model> call() throws IOException {
if(!fc2live.login()) { return loadModels();
throw new IOException("Login didn't work");
}
RequestBody body = new FormBody.Builder()
.add("mode", "list")
.add("page", Integer.toString(page - 1))
.build();
Request req = new Request.Builder()
.url(fc2live.getBaseUrl() + "/api/favoriteManager.php")
.header(REFERER, fc2live.getBaseUrl())
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.header("Content-Type", "application/x-www-form-urlencoded")
.post(body)
.build();
try(Response resp = fc2live.getHttpClient().execute(req)) {
if(resp.isSuccessful()) {
List<Model> models = new ArrayList<>();
String content = resp.body().string();
JSONObject json = new JSONObject(content);
if(json.optInt("status") == 1) {
JSONArray data = json.getJSONArray("data");
for (int i = 0; i < data.length(); i++) {
JSONObject m = data.getJSONObject(i);
Fc2Model model = (Fc2Model) fc2live.createModel(m.getString("name"));
model.setId(m.getString("id"));
model.setUrl(Fc2Live.BASE_URL + '/' + model.getId());
String previewUrl = m.optString("icon");
if(previewUrl == null || previewUrl.trim().isEmpty()) {
previewUrl = "https://live-storage.fc2.com/thumb/" + model.getId() + "/thumb.jpg";
}
model.setPreview(previewUrl);
model.setDescription("");
models.add(model);
}
return models;
} else {
throw new IOException("Request was not successful: " + json.toString());
}
} else {
throw new HttpException(resp.code(), resp.message());
}
}
} }
}; };
} }
public void setShowOnline(boolean online) { private List<Model> loadModels() throws IOException {
//this.online = online; if(!fc2live.login()) {
throw new IOException("Login didn't work");
}
RequestBody body = new FormBody.Builder()
.add("mode", "list")
.add("page", Integer.toString(page - 1))
.build();
Request req = new Request.Builder()
.url(fc2live.getBaseUrl() + "/api/favoriteManager.php")
.header(REFERER, fc2live.getBaseUrl())
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.header("Content-Type", "application/x-www-form-urlencoded")
.post(body)
.build();
try (Response resp = fc2live.getHttpClient().execute(req)) {
if (resp.isSuccessful()) {
List<Model> models = new ArrayList<>();
var content = resp.body().string();
var json = new JSONObject(content);
if (json.optInt("status") == 1) {
var data = json.getJSONArray("data");
for (var i = 0; i < data.length(); i++) {
var m = data.getJSONObject(i);
Fc2Model model = (Fc2Model) fc2live.createModel(m.getString("name"));
model.setId(m.getString("id"));
model.setUrl(Fc2Live.BASE_URL + '/' + model.getId());
var previewUrl = m.optString("icon");
if (previewUrl == null || previewUrl.trim().isEmpty()) {
previewUrl = "https://live-storage.fc2.com/thumb/" + model.getId() + "/thumb.jpg";
}
model.setPreview(previewUrl);
model.setDescription("");
models.add(model);
}
return models;
} else {
throw new IOException("Request was not successful: " + json.toString());
}
} else {
throw new HttpException(resp.code(), resp.message());
}
}
}
public void setShowOnline(boolean yes) {
// not implemented yet
} }
} }

View File

@ -1,7 +1,6 @@
package ctbrec.ui.sites.fc2live; package ctbrec.ui.sites.fc2live;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.Settings;
import ctbrec.sites.fc2live.Fc2Live; import ctbrec.sites.fc2live.Fc2Live;
import ctbrec.ui.DesktopIntegration; import ctbrec.ui.DesktopIntegration;
import ctbrec.ui.settings.SettingsTab; import ctbrec.ui.settings.SettingsTab;
@ -25,15 +24,15 @@ public class Fc2LiveConfigUI extends AbstractConfigUI {
@Override @Override
public Parent createConfigPanel() { public Parent createConfigPanel() {
GridPane layout = SettingsTab.createGridLayout(); var layout = SettingsTab.createGridLayout();
Settings settings = Config.getInstance().getSettings(); var settings = Config.getInstance().getSettings();
int row = 0; var row = 0;
Label l = new Label("Active"); var l = new Label("Active");
layout.add(l, 0, row); layout.add(l, 0, row);
CheckBox enabled = new CheckBox(); var enabled = new CheckBox();
enabled.setSelected(!settings.disabledSites.contains(fc2live.getName())); enabled.setSelected(!settings.disabledSites.contains(fc2live.getName()));
enabled.setOnAction((e) -> { enabled.setOnAction(e -> {
if(enabled.isSelected()) { if(enabled.isSelected()) {
settings.disabledSites.remove(fc2live.getName()); settings.disabledSites.remove(fc2live.getName());
} else { } else {
@ -45,7 +44,7 @@ public class Fc2LiveConfigUI extends AbstractConfigUI {
layout.add(enabled, 1, row++); layout.add(enabled, 1, row++);
layout.add(new Label("FC2Live User"), 0, row); layout.add(new Label("FC2Live User"), 0, row);
TextField username = new TextField(settings.fc2liveUsername); var username = new TextField(settings.fc2liveUsername);
username.textProperty().addListener((ob, o, n) -> { username.textProperty().addListener((ob, o, n) -> {
if(!n.equals(Config.getInstance().getSettings().fc2liveUsername)) { if(!n.equals(Config.getInstance().getSettings().fc2liveUsername)) {
Config.getInstance().getSettings().fc2liveUsername = username.getText(); Config.getInstance().getSettings().fc2liveUsername = username.getText();
@ -59,7 +58,7 @@ public class Fc2LiveConfigUI extends AbstractConfigUI {
layout.add(username, 1, row++); layout.add(username, 1, row++);
layout.add(new Label("FC2Live Password"), 0, row); layout.add(new Label("FC2Live Password"), 0, row);
PasswordField password = new PasswordField(); var password = new PasswordField();
password.setText(settings.fc2livePassword); password.setText(settings.fc2livePassword);
password.textProperty().addListener((ob, o, n) -> { password.textProperty().addListener((ob, o, n) -> {
if(!n.equals(Config.getInstance().getSettings().fc2livePassword)) { if(!n.equals(Config.getInstance().getSettings().fc2livePassword)) {
@ -73,9 +72,9 @@ public class Fc2LiveConfigUI extends AbstractConfigUI {
GridPane.setColumnSpan(password, 2); GridPane.setColumnSpan(password, 2);
layout.add(password, 1, row++); layout.add(password, 1, row++);
Button createAccount = new Button("Create new Account"); var createAccount = new Button("Create new Account");
createAccount.setOnAction((e) -> DesktopIntegration.open(fc2live.getAffiliateLink())); createAccount.setOnAction(e -> DesktopIntegration.open(fc2live.getAffiliateLink()));
layout.add(createAccount, 1, row++); layout.add(createAccount, 1, row);
GridPane.setColumnSpan(createAccount, 2); GridPane.setColumnSpan(createAccount, 2);
GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN)); GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN)); GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));

View File

@ -9,7 +9,7 @@ import ctbrec.ui.tabs.ThumbOverviewTab;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
public class Fc2TabProvider extends TabProvider { public class Fc2TabProvider implements TabProvider {
private Fc2Live fc2live; private Fc2Live fc2live;
private Fc2FollowedTab followed; private Fc2FollowedTab followed;
@ -31,8 +31,8 @@ public class Fc2TabProvider extends TabProvider {
} }
private Tab createTab(String title, String url) { private Tab createTab(String title, String url) {
Fc2UpdateService updateService = new Fc2UpdateService(url, fc2live); var updateService = new Fc2UpdateService(url, fc2live);
ThumbOverviewTab tab = new ThumbOverviewTab(title, updateService, fc2live); var tab = new ThumbOverviewTab(title, updateService, fc2live);
tab.setRecorder(fc2live.getRecorder()); tab.setRecorder(fc2live.getRecorder());
return tab; return tab;
} }

View File

@ -8,7 +8,6 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -22,7 +21,6 @@ import ctbrec.ui.tabs.PaginatedScheduledService;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.RequestBody; import okhttp3.RequestBody;
import okhttp3.Response;
public class Fc2UpdateService extends PaginatedScheduledService { public class Fc2UpdateService extends PaginatedScheduledService {
private static final Logger LOG = LoggerFactory.getLogger(Fc2UpdateService.class); private static final Logger LOG = LoggerFactory.getLogger(Fc2UpdateService.class);
@ -41,7 +39,7 @@ public class Fc2UpdateService extends PaginatedScheduledService {
return new Task<List<Model>>() { return new Task<List<Model>>() {
@Override @Override
public List<Model> call() throws IOException { public List<Model> call() throws IOException {
RequestBody body = RequestBody.create(new byte[0]); var body = RequestBody.create(new byte[0]);
Request req = new Request.Builder() Request req = new Request.Builder()
.url(url) .url(url)
.method("POST", body) .method("POST", body)
@ -52,31 +50,31 @@ public class Fc2UpdateService extends PaginatedScheduledService {
.header(X_REQUESTED_WITH, XML_HTTP_REQUEST) .header(X_REQUESTED_WITH, XML_HTTP_REQUEST)
.build(); .build();
LOG.debug("Fetching page {}", url); LOG.debug("Fetching page {}", url);
try(Response resp = fc2live.getHttpClient().execute(req)) { try (var resp = fc2live.getHttpClient().execute(req)) {
if(resp.isSuccessful()) { if (resp.isSuccessful()) {
List<Fc2Model> models = new ArrayList<>(); List<Fc2Model> models = new ArrayList<>();
String msg = resp.body().string(); var msg = resp.body().string();
JSONObject json = new JSONObject(msg); var json = new JSONObject(msg);
JSONArray channels = json.getJSONArray("channel"); var channels = json.getJSONArray("channel");
for (int i = 0; i < channels.length(); i++) { for (var i = 0; i < channels.length(); i++) {
JSONObject channel = channels.getJSONObject(i); var channel = channels.getJSONObject(i);
Fc2Model model = (Fc2Model) fc2live.createModel(channel.getString("name")); Fc2Model model = (Fc2Model) fc2live.createModel(channel.getString("name"));
model.setId(channel.getString("id")); model.setId(channel.getString("id"));
model.setUrl(Fc2Live.BASE_URL + '/' + model.getId()); model.setUrl(Fc2Live.BASE_URL + '/' + model.getId());
String previewUrl = channel.getString("image"); var previewUrl = channel.getString("image");
if(previewUrl == null || previewUrl.trim().isEmpty()) { if (previewUrl == null || previewUrl.trim().isEmpty()) {
previewUrl = getClass().getResource("/image_not_found.png").toString(); previewUrl = getClass().getResource("/image_not_found.png").toString();
} }
model.setPreview(previewUrl); model.setPreview(previewUrl);
model.setDescription(channel.optString("title")); model.setDescription(channel.optString("title"));
model.setViewerCount(channel.optInt("count")); model.setViewerCount(channel.optInt("count"));
if(channel.getInt("login") == 0) { if (channel.getInt("login") == 0) {
models.add(model); models.add(model);
} }
} }
return models.stream() return models.stream()
.sorted((m1, m2) -> m2.getViewerCount() - m1.getViewerCount()) .sorted((m1, m2) -> m2.getViewerCount() - m1.getViewerCount())
.skip( (long)(page - 1) * modelsPerPage) .skip((long) (page - 1) * modelsPerPage)
.limit(modelsPerPage) .limit(modelsPerPage)
.collect(Collectors.toList()); .collect(Collectors.toList());
} else { } else {

View File

@ -1,7 +1,6 @@
package ctbrec.ui.sites.flirt4free; package ctbrec.ui.sites.flirt4free;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.Settings;
import ctbrec.sites.flirt4free.Flirt4Free; import ctbrec.sites.flirt4free.Flirt4Free;
import ctbrec.ui.DesktopIntegration; import ctbrec.ui.DesktopIntegration;
import ctbrec.ui.settings.SettingsTab; import ctbrec.ui.settings.SettingsTab;
@ -25,15 +24,15 @@ public class Flirt4FreeConfigUI extends AbstractConfigUI {
@Override @Override
public Parent createConfigPanel() { public Parent createConfigPanel() {
GridPane layout = SettingsTab.createGridLayout(); var layout = SettingsTab.createGridLayout();
Settings settings = Config.getInstance().getSettings(); var settings = Config.getInstance().getSettings();
int row = 0; var row = 0;
Label l = new Label("Active"); var l = new Label("Active");
layout.add(l, 0, row); layout.add(l, 0, row);
CheckBox enabled = new CheckBox(); var enabled = new CheckBox();
enabled.setSelected(!settings.disabledSites.contains(flirt4free.getName())); enabled.setSelected(!settings.disabledSites.contains(flirt4free.getName()));
enabled.setOnAction((e) -> { enabled.setOnAction(e -> {
if(enabled.isSelected()) { if(enabled.isSelected()) {
settings.disabledSites.remove(flirt4free.getName()); settings.disabledSites.remove(flirt4free.getName());
} else { } else {
@ -45,7 +44,7 @@ public class Flirt4FreeConfigUI extends AbstractConfigUI {
layout.add(enabled, 1, row++); layout.add(enabled, 1, row++);
layout.add(new Label("Flirt4Free User"), 0, row); layout.add(new Label("Flirt4Free User"), 0, row);
TextField username = new TextField(settings.flirt4freeUsername); var username = new TextField(settings.flirt4freeUsername);
username.textProperty().addListener((ob, o, n) -> { username.textProperty().addListener((ob, o, n) -> {
if(!n.equals(Config.getInstance().getSettings().flirt4freeUsername)) { if(!n.equals(Config.getInstance().getSettings().flirt4freeUsername)) {
Config.getInstance().getSettings().flirt4freeUsername = username.getText(); Config.getInstance().getSettings().flirt4freeUsername = username.getText();
@ -59,7 +58,7 @@ public class Flirt4FreeConfigUI extends AbstractConfigUI {
layout.add(username, 1, row++); layout.add(username, 1, row++);
layout.add(new Label("Flirt4Free Password"), 0, row); layout.add(new Label("Flirt4Free Password"), 0, row);
PasswordField password = new PasswordField(); var password = new PasswordField();
password.setText(settings.flirt4freePassword); password.setText(settings.flirt4freePassword);
password.textProperty().addListener((ob, o, n) -> { password.textProperty().addListener((ob, o, n) -> {
if(!n.equals(Config.getInstance().getSettings().flirt4freePassword)) { if(!n.equals(Config.getInstance().getSettings().flirt4freePassword)) {
@ -73,9 +72,9 @@ public class Flirt4FreeConfigUI extends AbstractConfigUI {
GridPane.setColumnSpan(password, 2); GridPane.setColumnSpan(password, 2);
layout.add(password, 1, row++); layout.add(password, 1, row++);
Button createAccount = new Button("Create new Account"); var createAccount = new Button("Create new Account");
createAccount.setOnAction((e) -> DesktopIntegration.open(flirt4free.getAffiliateLink())); createAccount.setOnAction(e -> DesktopIntegration.open(flirt4free.getAffiliateLink()));
layout.add(createAccount, 1, row++); layout.add(createAccount, 1, row);
GridPane.setColumnSpan(createAccount, 2); GridPane.setColumnSpan(createAccount, 2);
GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN)); GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN)); GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));

View File

@ -15,10 +15,8 @@ public class Flirt4FreeFavoritesTab extends ThumbOverviewTab implements Followed
public void setScene(Scene scene) { public void setScene(Scene scene) {
scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> { scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if(this.isSelected()) { if (this.isSelected() && event.getCode() == KeyCode.DELETE) {
if(event.getCode() == KeyCode.DELETE) { follow(selectedThumbCells, false);
follow(selectedThumbCells, false);
}
} }
}); });
} }

View File

@ -21,7 +21,6 @@ import ctbrec.ui.SiteUiFactory;
import ctbrec.ui.tabs.PaginatedScheduledService; import ctbrec.ui.tabs.PaginatedScheduledService;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response;
public class Flirt4FreeFavoritesUpdateService extends PaginatedScheduledService { public class Flirt4FreeFavoritesUpdateService extends PaginatedScheduledService {
private Flirt4Free flirt4free; private Flirt4Free flirt4free;
@ -35,45 +34,49 @@ public class Flirt4FreeFavoritesUpdateService extends PaginatedScheduledService
return new Task<List<Model>>() { return new Task<List<Model>>() {
@Override @Override
public List<Model> call() throws IOException { public List<Model> call() throws IOException {
List<Model> models = new ArrayList<>(); return loadModelList();
String url = flirt4free.getBaseUrl() + "/my-account/secure/favorites.php?a=models&sort=online&status=all&pg=" + page;
SiteUiFactory.getUi(flirt4free).login();
Request request = new Request.Builder()
.url(url)
.header(ACCEPT, "*/*")
.header(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage())
.header(REFERER, flirt4free.getBaseUrl())
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.build();
try (Response response = flirt4free.getHttpClient().execute(request)) {
if (response.isSuccessful()) {
String body = response.body().string();
Elements modelContainers = HtmlParser.getTags(body, "div.model-container");
for (Element modelContainer : modelContainers) {
String modelHtml = modelContainer.html();
Element bioLink = HtmlParser.getTag(modelHtml, "a.common-link");
bioLink.setBaseUri(flirt4free.getBaseUrl());
Flirt4FreeModel model = (Flirt4FreeModel) flirt4free.createModelFromUrl(bioLink.absUrl("href"));
Element img = HtmlParser.getTag(modelHtml, "a > img[alt]");
model.setDisplayName(img.attr("alt"));
model.setPreview(img.attr("src"));
model.setDescription("");
model.setOnline(modelHtml.contains("I'm Online"));
try {
model.setOnlineState(model.isOnline() ? Model.State.ONLINE : Model.State.OFFLINE);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
// ignore
}
models.add(model);
}
return models;
} else {
throw new HttpException(response.code(), response.message());
}
}
} }
}; };
} }
private List<Model> loadModelList() throws IOException {
List<Model> models = new ArrayList<>();
String url = flirt4free.getBaseUrl() + "/my-account/secure/favorites.php?a=models&sort=online&status=all&pg=" + page;
SiteUiFactory.getUi(flirt4free).login();
var request = new Request.Builder()
.url(url)
.header(ACCEPT, "*/*")
.header(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage())
.header(REFERER, flirt4free.getBaseUrl())
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.build();
try (var response = flirt4free.getHttpClient().execute(request)) {
if (response.isSuccessful()) {
var body = response.body().string();
Elements modelContainers = HtmlParser.getTags(body, "div.model-container");
for (Element modelContainer : modelContainers) {
String modelHtml = modelContainer.html();
Element bioLink = HtmlParser.getTag(modelHtml, "a.common-link");
bioLink.setBaseUri(flirt4free.getBaseUrl());
Flirt4FreeModel model = (Flirt4FreeModel) flirt4free.createModelFromUrl(bioLink.absUrl("href"));
Element img = HtmlParser.getTag(modelHtml, "a > img[alt]");
model.setDisplayName(img.attr("alt"));
model.setPreview(img.attr("src"));
model.setDescription("");
model.setOnline(modelHtml.contains("I'm Online"));
try {
model.setOnlineState(model.isOnline() ? Model.State.ONLINE : Model.State.OFFLINE);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
// ignore
}
models.add(model);
}
return models;
} else {
throw new HttpException(response.code(), response.message());
}
}
}
} }

View File

@ -12,7 +12,7 @@ import javafx.scene.Scene;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import javafx.util.Duration; import javafx.util.Duration;
public class Flirt4FreeTabProvider extends TabProvider { public class Flirt4FreeTabProvider implements TabProvider {
private Flirt4Free flirt4Free; private Flirt4Free flirt4Free;
private ThumbOverviewTab followedTab; private ThumbOverviewTab followedTab;
@ -40,8 +40,8 @@ public class Flirt4FreeTabProvider extends TabProvider {
} }
private ThumbOverviewTab createTab(String title, String url, Predicate<Flirt4FreeModel> filter) { private ThumbOverviewTab createTab(String title, String url, Predicate<Flirt4FreeModel> filter) {
Flirt4FreeUpdateService s = new Flirt4FreeUpdateService(flirt4Free, url, filter); var s = new Flirt4FreeUpdateService(flirt4Free, url, filter);
ThumbOverviewTab tab = new ThumbOverviewTab(title, s, flirt4Free); var tab = new ThumbOverviewTab(title, s, flirt4Free);
tab.setRecorder(flirt4Free.getRecorder()); tab.setRecorder(flirt4Free.getRecorder());
s.setPeriod(Duration.seconds(60)); s.setPeriod(Duration.seconds(60));
return tab; return tab;

View File

@ -6,11 +6,9 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -45,11 +43,11 @@ public class Flirt4FreeUpdateService extends PaginatedScheduledService {
@Override @Override
public List<Model> call() throws IOException { public List<Model> call() throws IOException {
LOG.debug("Fetching page {}", url); LOG.debug("Fetching page {}", url);
Request request = new Request.Builder() var request = new Request.Builder()
.url(url) .url(url)
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent) .header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.build(); .build();
try (Response response = flirt4Free.getHttpClient().execute(request)) { try (var response = flirt4Free.getHttpClient().execute(request)) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
return parseResponse(response); return parseResponse(response);
} else { } else {
@ -62,26 +60,24 @@ public class Flirt4FreeUpdateService extends PaginatedScheduledService {
private List<Model> parseResponse(Response response) throws IOException { private List<Model> parseResponse(Response response) throws IOException {
List<Flirt4FreeModel> models = new ArrayList<>(); List<Flirt4FreeModel> models = new ArrayList<>();
String body = response.body().string(); var body = response.body().string();
Matcher m = Pattern.compile("window\\.__homePageData__ = (\\{.*\\})", Pattern.DOTALL).matcher(body); var m = Pattern.compile("window\\.__homePageData__ = (\\{.*\\})", Pattern.DOTALL).matcher(body);
if (m.find()) { if (m.find()) {
JSONObject data = new JSONObject(m.group(1)); var data = new JSONObject(m.group(1));
JSONArray modelData = data.getJSONArray("models"); var modelData = data.getJSONArray("models");
LOG.debug("Found {} models", modelData.length()); LOG.debug("Found {} models", modelData.length());
for (int i = 0; i < modelData.length(); i++) { for (var i = 0; i < modelData.length(); i++) {
JSONObject modelJson = modelData.getJSONObject(i); var modelJson = modelData.getJSONObject(i);
try { try {
Flirt4FreeModel model = parseModel(modelJson); Flirt4FreeModel model = parseModel(modelJson);
if (model != null) { models.add(model);
models.add(model);
}
} catch(Exception e) { } catch(Exception e) {
LOG.warn("Couldn't parse model {}", modelJson); LOG.warn("Couldn't parse model {}", modelJson);
} }
} }
return models.stream() return models.stream()
.filter(filter) .filter(filter)
.skip((page - 1) * MODELS_PER_PAGE) .skip((page - 1) * (long)MODELS_PER_PAGE)
.limit(MODELS_PER_PAGE) .limit(MODELS_PER_PAGE)
.collect(Collectors.toList()); .collect(Collectors.toList());
} else { } else {
@ -90,14 +86,14 @@ public class Flirt4FreeUpdateService extends PaginatedScheduledService {
} }
private Flirt4FreeModel parseModel(JSONObject modelData) { private Flirt4FreeModel parseModel(JSONObject modelData) {
String name = modelData.getString("model_seo_name"); var name = modelData.getString("model_seo_name");
Flirt4FreeModel model = (Flirt4FreeModel) flirt4Free.createModel(name); Flirt4FreeModel model = (Flirt4FreeModel) flirt4Free.createModel(name);
model.setDisplayName(modelData.getString("display")); model.setDisplayName(modelData.getString("display"));
model.setDescription(modelData.getString("topic")); model.setDescription(modelData.getString("topic"));
model.setUrl(Flirt4Free.BASE_URI + "/rooms/" + model.getName() + '/'); model.setUrl(Flirt4Free.BASE_URI + "/rooms/" + model.getName() + '/');
model.setNew(modelData.optString("is_new", "0").equals("1")); model.setNew(modelData.optString("is_new", "0").equals("1"));
String videoHost = modelData.getString("video_host"); var videoHost = modelData.getString("video_host");
String modelId = modelData.getString("model_id"); var modelId = modelData.getString("model_id");
model.setId(modelId); model.setId(modelId);
String streamUrl = "https://manifest.vscdns.com/manifest.m3u8.m3u8?key=nil&provider=level3&secure=true&host=" + videoHost String streamUrl = "https://manifest.vscdns.com/manifest.m3u8.m3u8?key=nil&provider=level3&secure=true&host=" + videoHost
+ "&model_id=" + modelId; + "&model_id=" + modelId;

View File

@ -1,7 +1,6 @@
package ctbrec.ui.sites.jasmin; package ctbrec.ui.sites.jasmin;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.Settings;
import ctbrec.sites.jasmin.LiveJasmin; import ctbrec.sites.jasmin.LiveJasmin;
import ctbrec.ui.DesktopIntegration; import ctbrec.ui.DesktopIntegration;
import ctbrec.ui.settings.SettingsTab; import ctbrec.ui.settings.SettingsTab;
@ -25,15 +24,15 @@ public class LiveJasminConfigUi extends AbstractConfigUI {
@Override @Override
public Parent createConfigPanel() { public Parent createConfigPanel() {
Settings settings = Config.getInstance().getSettings(); var settings = Config.getInstance().getSettings();
GridPane layout = SettingsTab.createGridLayout(); var layout = SettingsTab.createGridLayout();
int row = 0; var row = 0;
Label l = new Label("Active"); var l = new Label("Active");
layout.add(l, 0, row); layout.add(l, 0, row);
CheckBox enabled = new CheckBox(); var enabled = new CheckBox();
enabled.setSelected(!settings.disabledSites.contains(liveJasmin.getName())); enabled.setSelected(!settings.disabledSites.contains(liveJasmin.getName()));
enabled.setOnAction((e) -> { enabled.setOnAction(e -> {
if(enabled.isSelected()) { if(enabled.isSelected()) {
settings.disabledSites.remove(liveJasmin.getName()); settings.disabledSites.remove(liveJasmin.getName());
} else { } else {
@ -45,7 +44,7 @@ public class LiveJasminConfigUi extends AbstractConfigUI {
layout.add(enabled, 1, row++); layout.add(enabled, 1, row++);
layout.add(new Label("LiveJasmin User"), 0, row); layout.add(new Label("LiveJasmin User"), 0, row);
TextField username = new TextField(Config.getInstance().getSettings().livejasminUsername); var username = new TextField(Config.getInstance().getSettings().livejasminUsername);
username.textProperty().addListener((ob, o, n) -> { username.textProperty().addListener((ob, o, n) -> {
if(!n.equals(Config.getInstance().getSettings().livejasminUsername)) { if(!n.equals(Config.getInstance().getSettings().livejasminUsername)) {
Config.getInstance().getSettings().livejasminUsername = n; Config.getInstance().getSettings().livejasminUsername = n;
@ -59,7 +58,7 @@ public class LiveJasminConfigUi extends AbstractConfigUI {
layout.add(username, 1, row++); layout.add(username, 1, row++);
layout.add(new Label("LiveJasmin Password"), 0, row); layout.add(new Label("LiveJasmin Password"), 0, row);
PasswordField password = new PasswordField(); var password = new PasswordField();
password.setText(Config.getInstance().getSettings().livejasminPassword); password.setText(Config.getInstance().getSettings().livejasminPassword);
password.textProperty().addListener((ob, o, n) -> { password.textProperty().addListener((ob, o, n) -> {
if(!n.equals(Config.getInstance().getSettings().livejasminPassword)) { if(!n.equals(Config.getInstance().getSettings().livejasminPassword)) {
@ -74,7 +73,7 @@ public class LiveJasminConfigUi extends AbstractConfigUI {
layout.add(password, 1, row++); layout.add(password, 1, row++);
layout.add(new Label("LiveJasmin Base URL"), 0, row); layout.add(new Label("LiveJasmin Base URL"), 0, row);
TextField baseUrl = new TextField(); var baseUrl = new TextField();
baseUrl.setText(Config.getInstance().getSettings().livejasminBaseUrl); baseUrl.setText(Config.getInstance().getSettings().livejasminBaseUrl);
baseUrl.textProperty().addListener((ob, o, n) -> { baseUrl.textProperty().addListener((ob, o, n) -> {
Config.getInstance().getSettings().livejasminBaseUrl = baseUrl.getText(); Config.getInstance().getSettings().livejasminBaseUrl = baseUrl.getText();
@ -85,9 +84,9 @@ public class LiveJasminConfigUi extends AbstractConfigUI {
GridPane.setColumnSpan(baseUrl, 2); GridPane.setColumnSpan(baseUrl, 2);
layout.add(baseUrl, 1, row++); layout.add(baseUrl, 1, row++);
Button createAccount = new Button("Create new Account"); var createAccount = new Button("Create new Account");
createAccount.setOnAction((e) -> DesktopIntegration.open(liveJasmin.getAffiliateLink())); createAccount.setOnAction(e -> DesktopIntegration.open(liveJasmin.getAffiliateLink()));
layout.add(createAccount, 1, row++); layout.add(createAccount, 1, row);
GridPane.setColumnSpan(createAccount, 2); GridPane.setColumnSpan(createAccount, 2);
GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN)); GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN)); GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));

View File

@ -4,7 +4,6 @@ import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -19,23 +18,24 @@ import okhttp3.HttpUrl;
public class LiveJasminElectronLoginDialog { public class LiveJasminElectronLoginDialog {
private static final transient Logger LOG = LoggerFactory.getLogger(LiveJasminElectronLoginDialog.class); private static final Logger LOG = LoggerFactory.getLogger(LiveJasminElectronLoginDialog.class);
public static final String URL = LiveJasmin.baseUrl + "/en/auth/login"; public static final String URL = LiveJasmin.baseUrl + "/en/auth/login";
private CookieJar cookieJar; private CookieJar cookieJar;
private ExternalBrowser browser; private ExternalBrowser browser;
public LiveJasminElectronLoginDialog(CookieJar cookieJar) throws Exception { public LiveJasminElectronLoginDialog(CookieJar cookieJar) throws IOException {
this.cookieJar = cookieJar; this.cookieJar = cookieJar;
browser = ExternalBrowser.getInstance(); browser = ExternalBrowser.getInstance();
try { try {
JSONObject config = new JSONObject(); var config = new JSONObject();
config.put("url", URL); config.put("url", URL);
config.put("w", 640); config.put("w", 640);
config.put("h", 720); config.put("h", 720);
JSONObject msg = new JSONObject(); var msg = new JSONObject();
msg.put("config", config); msg.put("config", config);
browser.run(msg, msgHandler); browser.run(msg, msgHandler);
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException("Couldn't wait for login dialog", e); throw new IOException("Couldn't wait for login dialog", e);
} catch (IOException e) { } catch (IOException e) {
LOG.debug("Error while starting the browser or communication to it", e); LOG.debug("Error while starting the browser or communication to it", e);
@ -44,14 +44,13 @@ public class LiveJasminElectronLoginDialog {
} }
} }
private Consumer<String> msgHandler = (line) -> { private Consumer<String> msgHandler = line -> {
//LOG.debug("Browser: {}", line);
if(!line.startsWith("{")) { if(!line.startsWith("{")) {
System.err.println(line); System.err.println(line); // NOSONAR
} else { } else {
JSONObject json = new JSONObject(line); var json = new JSONObject(line);
if(json.has("url")) { if(json.has("url")) {
String url = json.getString("url"); var url = json.getString("url");
if(url.endsWith("/auth/login")) { if(url.endsWith("/auth/login")) {
try { try {
String username = Config.getInstance().getSettings().livejasminUsername; String username = Config.getInstance().getSettings().livejasminUsername;
@ -73,9 +72,9 @@ public class LiveJasminElectronLoginDialog {
} }
} }
if(json.has("cookies")) { if(json.has("cookies")) {
JSONArray _cookies = json.getJSONArray("cookies"); var cookiesFromBrowser = json.getJSONArray("cookies");
for (int i = 0; i < _cookies.length(); i++) { for (var i = 0; i < cookiesFromBrowser.length(); i++) {
JSONObject cookie = _cookies.getJSONObject(i); var cookie = cookiesFromBrowser.getJSONObject(i);
Builder b = new Cookie.Builder() Builder b = new Cookie.Builder()
.path("/") .path("/")
.domain(LiveJasmin.baseDomain) .domain(LiveJasmin.baseDomain)

View File

@ -15,10 +15,8 @@ public class LiveJasminFollowedTab extends LiveJasminTab implements FollowedTab
@Override @Override
public void setScene(Scene scene) { public void setScene(Scene scene) {
scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> { scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if(this.isSelected()) { if (this.isSelected() && event.getCode() == KeyCode.DELETE) {
if(event.getCode() == KeyCode.DELETE) { follow(selectedThumbCells, false);
follow(selectedThumbCells, false);
}
} }
}); });
} }

View File

@ -23,7 +23,6 @@ import ctbrec.ui.SiteUiFactory;
import ctbrec.ui.tabs.PaginatedScheduledService; import ctbrec.ui.tabs.PaginatedScheduledService;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response;
public class LiveJasminFollowedUpdateService extends PaginatedScheduledService { public class LiveJasminFollowedUpdateService extends PaginatedScheduledService {
@ -50,16 +49,16 @@ public class LiveJasminFollowedUpdateService extends PaginatedScheduledService {
throw new NotLoggedInExcetion("Couldn't login to livejasmin"); throw new NotLoggedInExcetion("Couldn't login to livejasmin");
} }
LOG.debug("Fetching page {}", url); LOG.debug("Fetching page {}", url);
Request request = new Request.Builder() var request = new Request.Builder()
.url(url) .url(url)
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent) .header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.header(ACCEPT, "*/*") .header(ACCEPT, "*/*")
.header(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage()) .header(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage())
.header(REFERER, liveJasmin.getBaseUrl()) .header(REFERER, liveJasmin.getBaseUrl())
.build(); .build();
try (Response response = liveJasmin.getHttpClient().execute(request)) { try (var response = liveJasmin.getHttpClient().execute(request)) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
String body = response.body().string(); var body = response.body().string();
List<Model> models = new ArrayList<>(); List<Model> models = new ArrayList<>();
Elements modelCells = getTags(body, "article[class~=perf_container]"); Elements modelCells = getTags(body, "article[class~=perf_container]");
for (Element modelCell : modelCells) { for (Element modelCell : modelCells) {

View File

@ -41,7 +41,7 @@ public class LiveJasminSiteUi extends AbstractSiteUi {
public synchronized boolean login() throws IOException { public synchronized boolean login() throws IOException {
// renew login every 30 min // renew login every 30 min
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
boolean renew = false; var renew = false;
if ((now - lastLoginTime) > TimeUnit.MINUTES.toMillis(30)) { if ((now - lastLoginTime) > TimeUnit.MINUTES.toMillis(30)) {
renew = true; renew = true;
} }

View File

@ -2,6 +2,9 @@ package ctbrec.ui.sites.jasmin;
import java.io.IOException; import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.sites.Site; import ctbrec.sites.Site;
import ctbrec.ui.tabs.PaginatedScheduledService; import ctbrec.ui.tabs.PaginatedScheduledService;
@ -14,6 +17,7 @@ import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent; import javafx.scene.input.KeyEvent;
public class LiveJasminTab extends ThumbOverviewTab { public class LiveJasminTab extends ThumbOverviewTab {
private static final Logger LOG = LoggerFactory.getLogger(LiveJasminTab.class);
protected Label status; protected Label status;
protected Button acknowledge = new Button("That's alright"); protected Button acknowledge = new Button("That's alright");
private boolean betaAcknowledged = Config.getInstance().getSettings().livejasminBetaAcknowledged; private boolean betaAcknowledged = Config.getInstance().getSettings().livejasminBetaAcknowledged;
@ -36,6 +40,7 @@ public class LiveJasminTab extends ThumbOverviewTab {
try { try {
Config.getInstance().save(); Config.getInstance().save();
} catch (IOException e1) { } catch (IOException e1) {
LOG.error("Couldn't save config", e1);
} }
status.setText("Loading..."); status.setText("Loading...");
grid.getChildren().remove(acknowledge); grid.getChildren().remove(acknowledge);
@ -47,11 +52,6 @@ public class LiveJasminTab extends ThumbOverviewTab {
}); });
} }
@Override
protected void createGui() {
super.createGui();
}
@Override @Override
protected void onSuccess() { protected void onSuccess() {
if(Config.getInstance().getSettings().livejasminBetaAcknowledged) { if(Config.getInstance().getSettings().livejasminBetaAcknowledged) {
@ -70,17 +70,10 @@ public class LiveJasminTab extends ThumbOverviewTab {
} }
} }
@Override
public void selected() {
super.selected();
}
public void setScene(Scene scene) { public void setScene(Scene scene) {
scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> { scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if(this.isSelected()) { if (this.isSelected() && event.getCode() == KeyCode.DELETE) {
if(event.getCode() == KeyCode.DELETE) { follow(selectedThumbCells, false);
follow(selectedThumbCells, false);
}
} }
}); });
} }

View File

@ -10,7 +10,7 @@ import javafx.scene.Scene;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import javafx.util.Duration; import javafx.util.Duration;
public class LiveJasminTabProvider extends TabProvider { public class LiveJasminTabProvider implements TabProvider {
private LiveJasmin liveJasmin; private LiveJasmin liveJasmin;
private LiveJasminFollowedTab followedTab; private LiveJasminFollowedTab followedTab;
@ -43,7 +43,7 @@ public class LiveJasminTabProvider extends TabProvider {
} }
private ThumbOverviewTab createTab(String title, String url) { private ThumbOverviewTab createTab(String title, String url) {
LiveJasminUpdateService s = new LiveJasminUpdateService(liveJasmin, url); var s = new LiveJasminUpdateService(liveJasmin, url);
s.setPeriod(Duration.seconds(60)); s.setPeriod(Duration.seconds(60));
ThumbOverviewTab tab = new LiveJasminTab(title, s, liveJasmin); ThumbOverviewTab tab = new LiveJasminTab(title, s, liveJasmin);
tab.setRecorder(liveJasmin.getRecorder()); tab.setRecorder(liveJasmin.getRecorder());

View File

@ -8,25 +8,21 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.io.CookieJarImpl;
import ctbrec.io.HttpException; import ctbrec.io.HttpException;
import ctbrec.sites.jasmin.LiveJasmin; import ctbrec.sites.jasmin.LiveJasmin;
import ctbrec.sites.jasmin.LiveJasminModel; import ctbrec.sites.jasmin.LiveJasminModel;
import ctbrec.ui.SiteUI;
import ctbrec.ui.SiteUiFactory; import ctbrec.ui.SiteUiFactory;
import ctbrec.ui.tabs.PaginatedScheduledService; import ctbrec.ui.tabs.PaginatedScheduledService;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import okhttp3.Cookie; import okhttp3.Cookie;
import okhttp3.HttpUrl; import okhttp3.HttpUrl;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response;
public class LiveJasminUpdateService extends PaginatedScheduledService { public class LiveJasminUpdateService extends PaginatedScheduledService {
@ -45,8 +41,8 @@ public class LiveJasminUpdateService extends PaginatedScheduledService {
@Override @Override
public List<Model> call() throws IOException { public List<Model> call() throws IOException {
// sort by popularity // sort by popularity
CookieJarImpl cookieJar = liveJasmin.getHttpClient().getCookieJar(); var cookieJar = liveJasmin.getHttpClient().getCookieJar();
Cookie sortCookie = new Cookie.Builder() var sortCookie = new Cookie.Builder()
.domain(LiveJasmin.baseDomain) .domain(LiveJasmin.baseDomain)
.name("listPageOrderType") .name("listPageOrderType")
.value("most_popular") .value("most_popular")
@ -55,7 +51,7 @@ public class LiveJasminUpdateService extends PaginatedScheduledService {
// TODO find out how to switch pages // TODO find out how to switch pages
LOG.debug("Fetching page {}", url); LOG.debug("Fetching page {}", url);
Request request = new Request.Builder() var request = new Request.Builder()
.url(url) .url(url)
.addHeader(USER_AGENT, Config.getInstance().getSettings().httpUserAgent) .addHeader(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.addHeader(ACCEPT, MIMETYPE_APPLICATION_JSON) .addHeader(ACCEPT, MIMETYPE_APPLICATION_JSON)
@ -63,31 +59,16 @@ public class LiveJasminUpdateService extends PaginatedScheduledService {
.addHeader(REFERER, liveJasmin.getBaseUrl()) .addHeader(REFERER, liveJasmin.getBaseUrl())
.addHeader(X_REQUESTED_WITH, XML_HTTP_REQUEST) .addHeader(X_REQUESTED_WITH, XML_HTTP_REQUEST)
.build(); .build();
try (Response response = liveJasmin.getHttpClient().execute(request)) { try (var response = liveJasmin.getHttpClient().execute(request)) {
LOG.debug("Response {} {}", response.code(), response.message()); LOG.debug("Response {} {}", response.code(), response.message());
if (response.isSuccessful()) { if (response.isSuccessful()) {
String body = response.body().string(); var body = response.body().string();
List<Model> models = new ArrayList<>(); List<Model> models = new ArrayList<>();
JSONObject json = new JSONObject(body); var json = new JSONObject(body);
//LOG.debug(json.toString(2));
if(json.optBoolean("success")) { if(json.optBoolean("success")) {
JSONObject data = json.getJSONObject("data"); parseModels(models, json);
JSONObject content = data.getJSONObject("content");
JSONArray performers = content.getJSONArray("performers");
for (int i = 0; i < performers.length(); i++) {
JSONObject m = performers.getJSONObject(i);
String name = m.optString("pid");
if(name.isEmpty()) {
continue;
}
LiveJasminModel model = (LiveJasminModel) liveJasmin.createModel(name);
model.setId(m.getString("id"));
model.setPreview(m.getString("profilePictureUrl"));
model.setOnlineState(LiveJasminModel.mapStatus(m.optInt("status")));
models.add(model);
}
} else if(json.optString("error").equals("Please login.")) { } else if(json.optString("error").equals("Please login.")) {
SiteUI siteUI = SiteUiFactory.getUi(liveJasmin); var siteUI = SiteUiFactory.getUi(liveJasmin);
if(siteUI.login()) { if(siteUI.login()) {
return call(); return call();
} else { } else {
@ -106,4 +87,22 @@ public class LiveJasminUpdateService extends PaginatedScheduledService {
} }
}; };
} }
private void parseModels(List<Model> models, JSONObject json) {
var data = json.getJSONObject("data");
var content = data.getJSONObject("content");
var performers = content.getJSONArray("performers");
for (var i = 0; i < performers.length(); i++) {
var m = performers.getJSONObject(i);
var name = m.optString("pid");
if(name.isEmpty()) {
continue;
}
LiveJasminModel model = (LiveJasminModel) liveJasmin.createModel(name);
model.setId(m.getString("id"));
model.setPreview(m.getString("profilePictureUrl"));
model.setOnlineState(LiveJasminModel.mapStatus(m.optInt("status")));
models.add(model);
}
}
} }

View File

@ -1,7 +1,6 @@
package ctbrec.ui.sites.manyvids; package ctbrec.ui.sites.manyvids;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.Settings;
import ctbrec.sites.manyvids.MVLive; import ctbrec.sites.manyvids.MVLive;
import ctbrec.ui.settings.SettingsTab; import ctbrec.ui.settings.SettingsTab;
import ctbrec.ui.sites.AbstractConfigUI; import ctbrec.ui.sites.AbstractConfigUI;
@ -20,15 +19,15 @@ public class MVLiveConfigUi extends AbstractConfigUI {
@Override @Override
public Parent createConfigPanel() { public Parent createConfigPanel() {
Settings settings = Config.getInstance().getSettings(); var settings = Config.getInstance().getSettings();
GridPane layout = SettingsTab.createGridLayout(); GridPane layout = SettingsTab.createGridLayout();
int row = 0; var row = 0;
Label l = new Label("Active"); var l = new Label("Active");
layout.add(l, 0, row); layout.add(l, 0, row);
CheckBox enabled = new CheckBox(); var enabled = new CheckBox();
enabled.setSelected(!settings.disabledSites.contains(site.getName())); enabled.setSelected(!settings.disabledSites.contains(site.getName()));
enabled.setOnAction((e) -> { enabled.setOnAction(e -> {
if(enabled.isSelected()) { if(enabled.isSelected()) {
settings.disabledSites.remove(site.getName()); settings.disabledSites.remove(site.getName());
} else { } else {
@ -37,7 +36,7 @@ public class MVLiveConfigUi extends AbstractConfigUI {
save(); save();
}); });
GridPane.setMargin(enabled, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN)); GridPane.setMargin(enabled, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
layout.add(enabled, 1, row++); layout.add(enabled, 1, row);
return layout; return layout;
} }
} }

View File

@ -9,7 +9,7 @@ import ctbrec.ui.tabs.ThumbOverviewTab;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
public class MVLiveTabProvider extends TabProvider { public class MVLiveTabProvider implements TabProvider {
private MVLive mvlive; private MVLive mvlive;
@ -26,8 +26,8 @@ public class MVLiveTabProvider extends TabProvider {
} }
private Tab createTab(String title) { private Tab createTab(String title) {
MVLiveUpdateService updateService = new MVLiveUpdateService(mvlive); var updateService = new MVLiveUpdateService(mvlive);
ThumbOverviewTab tab = new ThumbOverviewTab(title, updateService, mvlive); var tab = new ThumbOverviewTab(title, updateService, mvlive);
tab.setRecorder(mvlive.getRecorder()); tab.setRecorder(mvlive.getRecorder());
tab.setImageAspectRatio(1); tab.setImageAspectRatio(1);
return tab; return tab;

View File

@ -57,50 +57,59 @@ public class FriendsUpdateService extends PaginatedScheduledService {
.build(); .build();
try (Response resp = myFreeCams.getHttpClient().execute(req)) { try (Response resp = myFreeCams.getHttpClient().execute(req)) {
if (resp.isSuccessful()) { if (resp.isSuccessful()) {
String body = resp.body().string().substring(4); var body = resp.body().string().substring(4);
try { parseModels(body, models);
JSONObject json = new JSONObject(body);
for (String key : json.keySet()) {
int uid = Integer.parseInt(key);
MyFreeCamsModel model = MyFreeCamsClient.getInstance().getModel(uid);
if (model == null) {
JSONObject modelObject = json.getJSONObject(key);
String name = modelObject.getString("u");
model = myFreeCams.createModel(name);
SessionState st = new SessionState();
st.setM(new ctbrec.sites.mfc.Model());
st.getM().setCamscore(0.0);
st.setU(new User());
st.setUid(uid);
st.setLv(modelObject.getInt("lv"));
st.setVs(127);
}
models.add(model);
}
} catch (Exception e) {
LOG.info("Exception getting friends list. Response was: {}", body, e);
}
} else { } else {
LOG.error("Couldn't load friends list {} {}", resp.code(), resp.message()); LOG.error("Couldn't load friends list {} {}", resp.code(), resp.message());
} }
} }
boolean filterOnline = mode == Mode.ONLINE; boolean filterOnline = mode == Mode.ONLINE;
return models.stream().filter(m -> { return models.stream()
try { .filter(m -> {
return m.isOnline() == filterOnline; try {
} catch (Exception e) { return m.isOnline() == filterOnline;
return false; } catch (InterruptedException e) {
} Thread.currentThread().interrupt();
}) return false;
} catch (Exception e) {
return false;
}
})
.sorted((m1, m2) -> (int) (m2.getCamScore() - m1.getCamScore())) .sorted((m1, m2) -> (int) (m2.getCamScore() - m1.getCamScore()))
.skip((page - 1) * 50l) .skip((page - 1) * 50l)
.limit(50) .limit(50)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
} }
}; };
} }
private void parseModels(String body, List<MyFreeCamsModel> models) {
try {
var json = new JSONObject(body);
for (String key : json.keySet()) {
var uid = Integer.parseInt(key);
MyFreeCamsModel model = MyFreeCamsClient.getInstance().getModel(uid);
if (model == null) {
var modelObject = json.getJSONObject(key);
var name = modelObject.getString("u");
model = myFreeCams.createModel(name);
var st = new SessionState();
st.setM(new ctbrec.sites.mfc.Model());
st.getM().setCamscore(0.0);
st.setU(new User());
st.setUid(uid);
st.setLv(modelObject.getInt("lv"));
st.setVs(127);
}
models.add(model);
}
} catch (Exception e) {
LOG.info("Exception getting friends list. Response was: {}", body, e);
}
}
public void setMode(Mode mode) { public void setMode(Mode mode) {
this.mode = mode; this.mode = mode;
} }

View File

@ -20,8 +20,8 @@ public class HDCamsUpdateService extends PaginatedScheduledService {
return new Task<List<Model>>() { return new Task<List<Model>>() {
@Override @Override
public List<Model> call() throws IOException { public List<Model> call() throws IOException {
MyFreeCamsClient client = MyFreeCamsClient.getInstance(); var client = MyFreeCamsClient.getInstance();
int modelsPerPage = 50; var modelsPerPage = 50;
return client.getModels().stream() return client.getModels().stream()
.filter(m -> m.getPreview() != null) .filter(m -> m.getPreview() != null)
@ -33,7 +33,10 @@ public class HDCamsUpdateService extends PaginatedScheduledService {
.filter(m -> { .filter(m -> {
try { try {
return m.isOnline(); return m.isOnline();
} catch(Exception e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
} catch (Exception e) {
return false; return false;
} }
}) })

Some files were not shown because too many files have changed in this diff Show More