Code cleanup
This commit is contained in:
parent
7d23ebccfe
commit
ea062582d4
|
@ -11,11 +11,7 @@
|
|||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<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.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-15"/>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
|
|
|
@ -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.forbiddenReference=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
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ctbrec.docs;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.*;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
@ -7,7 +9,6 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
@ -32,13 +33,13 @@ public abstract class AbstractDocServlet extends HttpServlet {
|
|||
if(resourceAsStream == null) {
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
int length = 0;
|
||||
byte[] buffer = new byte[1024];
|
||||
var out = new ByteArrayOutputStream();
|
||||
var length = 0;
|
||||
var buffer = new byte[1024];
|
||||
while( (length = resourceAsStream.read(buffer)) >= 0 ) {
|
||||
out.write(buffer, 0, length);
|
||||
}
|
||||
return new String(out.toByteArray(), "utf-8");
|
||||
return new String(out.toByteArray(), UTF_8);
|
||||
}
|
||||
|
||||
String getHeader() throws IOException {
|
||||
|
@ -66,15 +67,15 @@ public abstract class AbstractDocServlet extends HttpServlet {
|
|||
|
||||
private void indexJar(URL resource, List<String> pages) throws IOException {
|
||||
String fileUrl = resource.getFile();
|
||||
fileUrl = URLDecoder.decode(fileUrl, StandardCharsets.UTF_8);
|
||||
fileUrl = URLDecoder.decode(fileUrl, UTF_8);
|
||||
int colon = fileUrl.indexOf(':');
|
||||
int exclamation = fileUrl.indexOf('!');
|
||||
String jar = fileUrl.substring(colon + 1, exclamation);
|
||||
String internalFile = fileUrl.substring(exclamation + 2);
|
||||
try (JarFile jarFile = new JarFile(jar)) {
|
||||
var jar = fileUrl.substring(colon + 1, exclamation);
|
||||
var internalFile = fileUrl.substring(exclamation + 2);
|
||||
try (var jarFile = new JarFile(jar)) {
|
||||
Enumeration<JarEntry> entries = jarFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
JarEntry jarEntry = entries.nextElement();
|
||||
var jarEntry = entries.nextElement();
|
||||
String name = jarEntry.getName();
|
||||
if (name.startsWith(internalFile) && name.toLowerCase().endsWith(".md")) {
|
||||
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) {
|
||||
File docs = new File(resource.getFile());
|
||||
var docs = new File(resource.getFile());
|
||||
String[] files = docs.list((dir, name) -> name.toLowerCase().endsWith(".md"));
|
||||
pages.addAll(Arrays.asList(files));
|
||||
}
|
||||
|
@ -94,15 +95,19 @@ public abstract class AbstractDocServlet extends HttpServlet {
|
|||
return loadFile(resource);
|
||||
}
|
||||
|
||||
protected void error(HttpServletResponse resp, int status, String message) throws IOException {
|
||||
resp.setStatus(status);
|
||||
resp.getWriter().println(getHeader());
|
||||
String html = loadFile("/html/docs/" + status + ".html");
|
||||
if(message == null || message.trim().isEmpty()) {
|
||||
message = "";
|
||||
protected void error(HttpServletResponse resp, int status, String message) {
|
||||
try {
|
||||
resp.setStatus(status);
|
||||
resp.getWriter().println(getHeader());
|
||||
String html = loadFile("/html/docs/" + status + ".html");
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,40 +16,41 @@ import org.slf4j.LoggerFactory;
|
|||
import ctbrec.servlet.StaticFileServlet;
|
||||
|
||||
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;
|
||||
|
||||
public synchronized static void start() throws Exception {
|
||||
private DocServer() {}
|
||||
|
||||
public static synchronized void start() throws Exception {
|
||||
if(started) {
|
||||
return;
|
||||
}
|
||||
|
||||
started = true;
|
||||
server = new Server();
|
||||
var server = new Server();
|
||||
|
||||
HttpConfiguration config = new HttpConfiguration();
|
||||
var config = new HttpConfiguration();
|
||||
config.setSendServerVersion(false);
|
||||
ServerConnector http = new ServerConnector(server, new HttpConnectionFactory(config));
|
||||
var http = new ServerConnector(server, new HttpConnectionFactory(config));
|
||||
http.setPort(5689);
|
||||
server.addConnector(http);
|
||||
|
||||
ServletHandler handler = new ServletHandler();
|
||||
var handler = new ServletHandler();
|
||||
server.setHandler(handler);
|
||||
HandlerList handlers = new HandlerList();
|
||||
var handlers = new HandlerList();
|
||||
handlers.setHandlers(new Handler[] { handler });
|
||||
server.setHandler(handlers);
|
||||
|
||||
MarkdownServlet markdownServlet = new MarkdownServlet();
|
||||
ServletHolder holder = new ServletHolder(markdownServlet);
|
||||
var markdownServlet = new MarkdownServlet();
|
||||
var holder = new ServletHolder(markdownServlet);
|
||||
handler.addServletWithMapping(holder, "/docs/*");
|
||||
|
||||
AbstractDocServlet searchServlet = new SearchServlet();
|
||||
holder = new ServletHolder(searchServlet);
|
||||
handler.addServletWithMapping(holder, "/search/*");
|
||||
|
||||
StaticFileServlet staticFileServlet = new StaticFileServlet("/html", false);
|
||||
var staticFileServlet = new StaticFileServlet("/html", false);
|
||||
holder = new ServletHolder(staticFileServlet);
|
||||
handler.addServletWithMapping(holder, "/static/*");
|
||||
|
||||
|
|
|
@ -38,16 +38,18 @@ public class MarkdownServlet extends AbstractDocServlet {
|
|||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
error(resp, HttpServletResponse.SC_NOT_FOUND, "");
|
||||
} catch (Exception e) {
|
||||
error(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "");
|
||||
}
|
||||
}
|
||||
|
||||
private void listPages(HttpServletResponse resp) throws IOException {
|
||||
List<String> pages = getPages();
|
||||
String html = "<ul>";
|
||||
var html = new StringBuilder("<ul>");
|
||||
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.getWriter().println(getHeader());
|
||||
resp.getWriter().println(html);
|
||||
|
@ -55,8 +57,8 @@ public class MarkdownServlet extends AbstractDocServlet {
|
|||
}
|
||||
|
||||
private String markdownToHtml(String markdown) {
|
||||
MutableDataSet options = new MutableDataSet();
|
||||
Parser parser = Parser.builder(options).build();
|
||||
var options = new MutableDataSet();
|
||||
var parser = Parser.builder(options).build();
|
||||
HtmlRenderer renderer = HtmlRenderer.builder(options).build();
|
||||
Node document = parser.parse(markdown);
|
||||
String html = renderer.render(document);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ctbrec.docs;
|
||||
|
||||
import static javax.servlet.http.HttpServletResponse.*;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
@ -9,41 +11,55 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.json.JSONArray;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SearchServlet extends AbstractDocServlet {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SearchServlet.class);
|
||||
private static final String Q = "term";
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
if(req.getParameter(Q) == null) {
|
||||
error(resp, HttpServletResponse.SC_BAD_REQUEST, "Parameter \""+Q+"\" is missing");
|
||||
return;
|
||||
try {
|
||||
if (req.getParameter(Q) == null) {
|
||||
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);
|
||||
resp.setContentType("application/json");
|
||||
JSONArray result = new JSONArray();
|
||||
List<String> pages = getPages();
|
||||
|
||||
String q = req.getParameter(Q).toLowerCase();
|
||||
String[] tokens = q.split("\\s+");
|
||||
private void searchPages(JSONArray result, List<String> pages, String[] tokens) throws IOException {
|
||||
for (String page : pages) {
|
||||
try {
|
||||
String content = loadMarkdown("/docs/" + page).toLowerCase();
|
||||
boolean allFound = true;
|
||||
var allFound = true;
|
||||
for (String token : tokens) {
|
||||
if(!content.contains(token)) {
|
||||
if (!content.contains(token)) {
|
||||
allFound = false;
|
||||
}
|
||||
}
|
||||
if(allFound) {
|
||||
if (allFound) {
|
||||
result.put(page);
|
||||
}
|
||||
} catch(FileNotFoundException e) {
|
||||
} catch (FileNotFoundException e) {
|
||||
// virtual page like index.md -> ignore
|
||||
}
|
||||
}
|
||||
resp.getWriter().println(result.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ public class AutosizeAlert extends Alert {
|
|||
setResizable(true);
|
||||
getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
|
||||
if(parent != null) {
|
||||
Stage stage = (Stage) getDialogPane().getScene().getWindow();
|
||||
var stage = (Stage) getDialogPane().getScene().getWindow();
|
||||
stage.getScene().getStylesheets().addAll(parent.getStylesheets());
|
||||
InputStream icon = Dialogs.class.getResourceAsStream("/icon.png");
|
||||
stage.getIcons().add(new Image(icon));
|
||||
|
|
|
@ -86,7 +86,6 @@ import javafx.scene.paint.Color;
|
|||
import javafx.stage.Stage;
|
||||
import javafx.stage.WindowEvent;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class CamrecApplication extends Application {
|
||||
|
||||
|
@ -104,7 +103,6 @@ public class CamrecApplication extends Application {
|
|||
public static HttpClient httpClient;
|
||||
public static String title;
|
||||
private Stage primaryStage;
|
||||
private RecordedTab modelsTab;
|
||||
private RecordingsTab recordingsTab;
|
||||
private ScheduledExecutorService scheduler;
|
||||
private int activeRecordings = 0;
|
||||
|
@ -114,7 +112,7 @@ public class CamrecApplication extends Application {
|
|||
public void start(Stage primaryStage) throws Exception {
|
||||
this.primaryStage = primaryStage;
|
||||
scheduler = Executors.newScheduledThreadPool(1, r -> {
|
||||
Thread t = new Thread(r);
|
||||
var t = new Thread(r);
|
||||
t.setDaemon(true);
|
||||
t.setName("Scheduler");
|
||||
return t;
|
||||
|
@ -172,7 +170,7 @@ public class CamrecApplication extends Application {
|
|||
|
||||
private void registerClipboardListener() {
|
||||
if (config.getSettings().monitorClipboard) {
|
||||
ClipboardListener clipboardListener = new ClipboardListener(recorder, sites);
|
||||
var clipboardListener = new ClipboardListener(recorder, sites);
|
||||
scheduler.scheduleAtFixedRate(clipboardListener, 0, 1, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
@ -209,19 +207,19 @@ public class CamrecApplication extends Application {
|
|||
int windowWidth = Config.getInstance().getSettings().windowWidth;
|
||||
int windowHeight = Config.getInstance().getSettings().windowHeight;
|
||||
|
||||
Scene scene = new Scene(rootPane, windowWidth, windowHeight);
|
||||
var scene = new Scene(rootPane, windowWidth, windowHeight);
|
||||
primaryStage.setScene(scene);
|
||||
Dialogs.setScene(scene);
|
||||
rootPane.setCenter(tabPane);
|
||||
rootPane.setBottom(statusBar);
|
||||
for (Site site : sites) {
|
||||
if (site.isEnabled()) {
|
||||
SiteTab siteTab = new SiteTab(site, scene);
|
||||
var siteTab = new SiteTab(site, scene);
|
||||
tabPane.getTabs().add(siteTab);
|
||||
}
|
||||
}
|
||||
|
||||
modelsTab = new RecordedTab(recorder, sites);
|
||||
var modelsTab = new RecordedTab(recorder, sites);
|
||||
tabPane.getTabs().add(modelsTab);
|
||||
recordingsTab = new RecordingsTab("Recordings", recorder, config);
|
||||
tabPane.getTabs().add(recordingsTab);
|
||||
|
@ -236,7 +234,7 @@ public class CamrecApplication extends Application {
|
|||
|
||||
switchToStartTab();
|
||||
writeColorSchemeStyleSheet();
|
||||
Color base = Color.web(Config.getInstance().getSettings().colorBase);
|
||||
var base = Color.web(Config.getInstance().getSettings().colorBase);
|
||||
if (!base.equals(Color.WHITE)) {
|
||||
loadStyleSheet(primaryStage, "color.css");
|
||||
}
|
||||
|
@ -308,7 +306,7 @@ public class CamrecApplication extends Application {
|
|||
}
|
||||
|
||||
// check for active recordings
|
||||
boolean shutdownNow = false;
|
||||
var shutdownNow = false;
|
||||
if (config.getSettings().localRecording) {
|
||||
try {
|
||||
if (!recorder.getCurrentlyRecording().isEmpty()) {
|
||||
|
@ -374,7 +372,7 @@ public class CamrecApplication extends Application {
|
|||
|
||||
private void registerAlertSystem() {
|
||||
for (EventHandlerConfiguration eventHandlerConfig : Config.getInstance().getSettings().eventHandlers) {
|
||||
EventHandler handler = new EventHandler(eventHandlerConfig);
|
||||
var handler = new EventHandler(eventHandlerConfig);
|
||||
EventBusHolder.register(handler);
|
||||
LOG.debug("Registered event handler for {} {}", eventHandlerConfig.getEvent(), eventHandlerConfig.getName());
|
||||
}
|
||||
|
@ -428,13 +426,13 @@ public class CamrecApplication extends Application {
|
|||
bytesPerSecond = 0;
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
private void writeColorSchemeStyleSheet() {
|
||||
File colorCss = new File(Config.getInstance().getConfigDir(), "color.css");
|
||||
try (FileOutputStream fos = new FileOutputStream(colorCss)) {
|
||||
var colorCss = new File(Config.getInstance().getConfigDir(), "color.css");
|
||||
try (var fos = new FileOutputStream(colorCss)) {
|
||||
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"
|
||||
+ " -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) {
|
||||
File css = new File(Config.getInstance().getConfigDir(), filename);
|
||||
var css = new File(Config.getInstance().getConfigDir(), filename);
|
||||
if (css.exists() && css.isFile()) {
|
||||
primaryStage.getScene().getStylesheets().add(css.toURI().toString());
|
||||
}
|
||||
|
@ -509,20 +507,20 @@ public class CamrecApplication extends Application {
|
|||
}
|
||||
|
||||
private void checkForUpdates() {
|
||||
Thread updateCheck = new Thread(() -> {
|
||||
String url = "https://pastebin.com/raw/mUxtKzyB";
|
||||
Request request = new Request.Builder().url(url).build();
|
||||
try (Response response = httpClient.execute(request)) {
|
||||
String body = response.body().string();
|
||||
var updateCheck = new Thread(() -> {
|
||||
var url = "https://pastebin.com/raw/mUxtKzyB";
|
||||
var request = new Request.Builder().url(url).build();
|
||||
try (var response = httpClient.execute(request)) {
|
||||
var body = response.body().string();
|
||||
LOG.trace("Version check respone: {}", body);
|
||||
if (response.isSuccessful()) {
|
||||
Moshi moshi = new Moshi.Builder().build();
|
||||
var moshi = new Moshi.Builder().build();
|
||||
Type type = Types.newParameterizedType(List.class, Release.class);
|
||||
JsonAdapter<List<Release>> adapter = moshi.adapter(type);
|
||||
List<Release> releases = adapter.fromJson(body);
|
||||
Release latest = releases.get(0);
|
||||
Version latestVersion = latest.getVersion();
|
||||
Version ctbrecVersion = getVersion();
|
||||
var latest = releases.get(0);
|
||||
var latestVersion = latest.getVersion();
|
||||
var ctbrecVersion = getVersion();
|
||||
if (latestVersion.compareTo(ctbrecVersion) > 0) {
|
||||
LOG.debug("Update available {} < {}", ctbrecVersion, latestVersion);
|
||||
Platform.runLater(() -> tabPane.getTabs().add(new UpdateTab(latest)));
|
||||
|
@ -546,8 +544,8 @@ public class CamrecApplication extends Application {
|
|||
return Version.of("0.0.0-DEV");
|
||||
} else {
|
||||
try (InputStream is = CamrecApplication.class.getClassLoader().getResourceAsStream("version")) {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
String versionString = reader.readLine();
|
||||
var reader = new BufferedReader(new InputStreamReader(is));
|
||||
var versionString = reader.readLine();
|
||||
return Version.of(versionString);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
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.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.List;
|
||||
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 {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ClipboardListener.class);
|
||||
|
@ -50,7 +50,7 @@ public class ClipboardListener implements Runnable {
|
|||
|
||||
private void addModelIfUrlMatches(String url) {
|
||||
for (Site site : sites) {
|
||||
Model m = site.createModelFromUrl(url);
|
||||
var m = site.createModelFromUrl(url);
|
||||
if (m != null) {
|
||||
try {
|
||||
recorder.addModel(m);
|
||||
|
|
|
@ -2,7 +2,6 @@ package ctbrec.ui;
|
|||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Desktop;
|
||||
import java.awt.Image;
|
||||
import java.awt.MenuItem;
|
||||
import java.awt.PopupMenu;
|
||||
import java.awt.SystemTray;
|
||||
|
@ -65,8 +64,8 @@ public class DesktopIntegration {
|
|||
}
|
||||
|
||||
// try external helpers
|
||||
String[] externalHelpers = { "kde-open5", "kde-open", "gnome-open", "xdg-open" };
|
||||
Runtime rt = Runtime.getRuntime();
|
||||
var externalHelpers = new String[] { "kde-open5", "kde-open", "gnome-open", "xdg-open" };
|
||||
var rt = Runtime.getRuntime();
|
||||
for (String helper : externalHelpers) {
|
||||
try {
|
||||
rt.exec(helper + " " + uri);
|
||||
|
@ -80,9 +79,9 @@ public class DesktopIntegration {
|
|||
Alert info = new AutosizeAlert(Alert.AlertType.ERROR);
|
||||
info.setTitle("Open URL");
|
||||
info.setContentText("Couldn't open URL");
|
||||
BorderPane pane = new BorderPane();
|
||||
var pane = new BorderPane();
|
||||
pane.setTop(new Label());
|
||||
TextField urlField = new TextField(uri);
|
||||
var urlField = new TextField(uri);
|
||||
urlField.setPadding(new Insets(10));
|
||||
urlField.setEditable(false);
|
||||
pane.setCenter(urlField);
|
||||
|
@ -100,8 +99,8 @@ public class DesktopIntegration {
|
|||
}
|
||||
|
||||
// try external helpers
|
||||
String[] externalHelpers = { "kde-open5", "kde-open", "gnome-open", "xdg-open" };
|
||||
Runtime rt = Runtime.getRuntime();
|
||||
var externalHelpers = new String[] { "kde-open5", "kde-open", "gnome-open", "xdg-open" };
|
||||
var rt = Runtime.getRuntime();
|
||||
for (String helper : externalHelpers) {
|
||||
try {
|
||||
rt.exec(helper + " " + f.getAbsolutePath());
|
||||
|
@ -115,9 +114,9 @@ public class DesktopIntegration {
|
|||
Alert info = new AutosizeAlert(Alert.AlertType.ERROR);
|
||||
info.setTitle("Open file");
|
||||
info.setContentText("Couldn't open file");
|
||||
BorderPane pane = new BorderPane();
|
||||
var pane = new BorderPane();
|
||||
pane.setTop(new Label());
|
||||
TextField urlField = new TextField(f.toString());
|
||||
var urlField = new TextField(f.toString());
|
||||
urlField.setPadding(new Insets(10));
|
||||
urlField.setEditable(false);
|
||||
pane.setCenter(urlField);
|
||||
|
@ -189,7 +188,7 @@ public class DesktopIntegration {
|
|||
if (tray == null) {
|
||||
String title = CamrecApplication.title;
|
||||
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);
|
||||
trayIcon = new TrayIcon(image, title, menu);
|
||||
|
@ -217,12 +216,12 @@ public class DesktopIntegration {
|
|||
}
|
||||
|
||||
private static PopupMenu createTrayContextMenu(Stage stage) {
|
||||
PopupMenu menu = new PopupMenu();
|
||||
MenuItem show = new MenuItem("Show");
|
||||
var menu = new PopupMenu();
|
||||
var show = new MenuItem("Show");
|
||||
show.addActionListener(evt -> restoreStage(stage));
|
||||
menu.add(show);
|
||||
menu.addSeparator();
|
||||
MenuItem pauseRecording = new MenuItem("Pause recording");
|
||||
var pauseRecording = new MenuItem("Pause recording");
|
||||
pauseRecording.addActionListener(evt -> {
|
||||
try {
|
||||
recorder.pause();
|
||||
|
@ -231,7 +230,7 @@ public class DesktopIntegration {
|
|||
}
|
||||
});
|
||||
menu.add(pauseRecording);
|
||||
MenuItem resumeRecording = new MenuItem("Resume recording");
|
||||
var resumeRecording = new MenuItem("Resume recording");
|
||||
resumeRecording.addActionListener(evt -> {
|
||||
try {
|
||||
recorder.resume();
|
||||
|
@ -241,8 +240,8 @@ public class DesktopIntegration {
|
|||
});
|
||||
menu.add(resumeRecording);
|
||||
menu.addSeparator();
|
||||
MenuItem exit = new MenuItem("Exit");
|
||||
exit.addActionListener(evt -> exit(stage));
|
||||
var exit = new MenuItem("Exit");
|
||||
exit.addActionListener(evt -> exit());
|
||||
menu.add(exit);
|
||||
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"));
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.OS;
|
||||
import ctbrec.Settings.ProxyType;
|
||||
import ctbrec.io.StreamRedirector;
|
||||
|
||||
public class ExternalBrowser implements AutoCloseable {
|
||||
|
@ -50,7 +49,7 @@ public class ExternalBrowser implements AutoCloseable {
|
|||
|
||||
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());
|
||||
Process p = new ProcessBuilder(cmdline).start();
|
||||
if (LOG.isTraceEnabled()) {
|
||||
|
@ -91,7 +90,7 @@ public class ExternalBrowser implements AutoCloseable {
|
|||
}
|
||||
|
||||
private void connectToRemoteControlSocket() throws IOException {
|
||||
for (int i = 0; i < 20; i++) {
|
||||
for (var i = 0; i < 20; i++) {
|
||||
try {
|
||||
socket = new Socket("localhost", 3202);
|
||||
in = socket.getInputStream();
|
||||
|
@ -117,7 +116,7 @@ public class ExternalBrowser implements AutoCloseable {
|
|||
}
|
||||
|
||||
public void executeJavaScript(String javaScript) throws IOException {
|
||||
JSONObject script = new JSONObject();
|
||||
var script = new JSONObject();
|
||||
script.put("execute", javaScript);
|
||||
out.write(script.toString().getBytes(UTF_8));
|
||||
out.write('\n');
|
||||
|
@ -138,7 +137,7 @@ public class ExternalBrowser implements AutoCloseable {
|
|||
|
||||
private void readBrowserOutput() {
|
||||
LOG.debug("Browser output reader started");
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
|
||||
try (var br = new BufferedReader(new InputStreamReader(in))) {
|
||||
String line;
|
||||
synchronized (browserReadyLock) {
|
||||
browserReady = true;
|
||||
|
@ -164,10 +163,10 @@ public class ExternalBrowser implements AutoCloseable {
|
|||
}
|
||||
|
||||
private void addProxyConfig(JSONObject jsonConfig) {
|
||||
ProxyType proxyType = Config.getInstance().getSettings().proxyType;
|
||||
var proxyType = Config.getInstance().getSettings().proxyType;
|
||||
switch (proxyType) {
|
||||
case HTTP:
|
||||
JSONObject proxy = new JSONObject();
|
||||
var proxy = new JSONObject();
|
||||
proxy.put("address",
|
||||
"http=" + Config.getInstance().getSettings().proxyHost + ':' + Config.getInstance().getSettings().proxyPort
|
||||
+ ";https=" + Config.getInstance().getSettings().proxyHost + ':' + Config.getInstance().getSettings().proxyPort);
|
||||
|
|
|
@ -12,7 +12,6 @@ import org.slf4j.LoggerFactory;
|
|||
import ctbrec.io.HttpClient;
|
||||
import ctbrec.recorder.ProgressListener;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class FileDownload {
|
||||
|
||||
|
@ -28,13 +27,13 @@ public class FileDownload {
|
|||
|
||||
public void start(URL url, File target) throws IOException {
|
||||
LOG.trace("Downloading file {} to {}", url, target);
|
||||
Request request = new Request.Builder().url(url).addHeader("connection", "keep-alive").build();
|
||||
Response response = httpClient.execute(request);
|
||||
long fileSize = Long.parseLong(response.header("Content-Length", String.valueOf(Long.MAX_VALUE)));
|
||||
var request = new Request.Builder().url(url).addHeader("connection", "keep-alive").build();
|
||||
var response = httpClient.execute(request);
|
||||
var fileSize = Long.parseLong(response.header("Content-Length", String.valueOf(Long.MAX_VALUE)));
|
||||
InputStream in = null;
|
||||
try (FileOutputStream fos = new FileOutputStream(target)) {
|
||||
try (var fos = new FileOutputStream(target)) {
|
||||
in = response.body().byteStream();
|
||||
byte[] b = new byte[1024 * 100];
|
||||
var b = new byte[1024 * 100];
|
||||
long totalBytesRead = 0;
|
||||
int length = -1;
|
||||
while ((length = in.read(b)) >= 0) {
|
||||
|
|
|
@ -23,54 +23,63 @@ public class CheckModelAccountAction {
|
|||
|
||||
private Recorder recorder;
|
||||
|
||||
private String buttonText;
|
||||
|
||||
public CheckModelAccountAction(Button b, Recorder recorder) {
|
||||
this.b = b;
|
||||
this.recorder = recorder;
|
||||
|
||||
buttonText = b.getText();
|
||||
}
|
||||
|
||||
public void execute(Predicate<Model> filter) {
|
||||
String buttonText = b.getText();
|
||||
b.setDisable(true);
|
||||
Runnable checker = (() -> {
|
||||
List<Model> deletedAccounts = new ArrayList<>();
|
||||
try {
|
||||
List<Model> models = recorder.getModels().stream() //
|
||||
.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);
|
||||
}
|
||||
}
|
||||
checkModelAccounts(filter, deletedAccounts);
|
||||
} finally {
|
||||
Platform.runLater(() -> {
|
||||
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();
|
||||
}
|
||||
}
|
||||
});
|
||||
showResult(deletedAccounts);
|
||||
}
|
||||
});
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import java.util.function.Consumer;
|
|||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Model;
|
||||
import ctbrec.Settings;
|
||||
import ctbrec.recorder.Recorder;
|
||||
import ctbrec.ui.JavaFxModel;
|
||||
import ctbrec.ui.controls.Dialogs;
|
||||
|
@ -29,8 +28,8 @@ public class IgnoreModelsAction {
|
|||
}
|
||||
|
||||
public void execute(Consumer<Model> callback) {
|
||||
Settings settings = Config.getInstance().getSettings();
|
||||
boolean confirmed = true;
|
||||
var settings = Config.getInstance().getSettings();
|
||||
var confirmed = true;
|
||||
if (settings.confirmationForDangerousActions) {
|
||||
int n = selectedModels.size();
|
||||
String plural = n > 1 ? "s" : "";
|
||||
|
@ -39,7 +38,7 @@ public class IgnoreModelsAction {
|
|||
}
|
||||
if (confirmed) {
|
||||
for (Model model : selectedModels) {
|
||||
Model modelToIgnore = unwrap(model);
|
||||
var modelToIgnore = unwrap(model);
|
||||
settings.ignoredModels.add(modelToIgnore.getUrl());
|
||||
}
|
||||
if (withRemoveDialog) {
|
||||
|
|
|
@ -24,7 +24,7 @@ public class OpenRecordingsDir {
|
|||
|
||||
public void execute() {
|
||||
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);
|
||||
if (dir.exists()) {
|
||||
GlobalThreadPool.submit(() -> DesktopIntegration.open(dir));
|
||||
|
@ -35,7 +35,7 @@ public class OpenRecordingsDir {
|
|||
}
|
||||
|
||||
private File getModelDirectory(File fileForRecording) {
|
||||
File dir = fileForRecording.getParentFile();
|
||||
var dir = fileForRecording.getParentFile();
|
||||
if (Config.getInstance().getSettings().recordingsDirStructure == DirectoryStructure.ONE_PER_RECORDING) {
|
||||
dir = dir.getParentFile();
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package ctbrec.ui.action;
|
|||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Model;
|
||||
import ctbrec.ui.SiteUI;
|
||||
import ctbrec.ui.SiteUiFactory;
|
||||
import ctbrec.ui.controls.Toast;
|
||||
import javafx.application.Platform;
|
||||
|
@ -21,8 +20,8 @@ public class PlayAction {
|
|||
|
||||
public void execute() {
|
||||
source.setCursor(Cursor.WAIT);
|
||||
Thread t = new Thread(() -> {
|
||||
SiteUI siteUI = SiteUiFactory.getUi(selectedModel.getSite());
|
||||
var t = new Thread(() -> {
|
||||
var siteUI = SiteUiFactory.getUi(selectedModel.getSite());
|
||||
boolean started = siteUI.play(selectedModel);
|
||||
Platform.runLater(() -> {
|
||||
if (started && Config.getInstance().getSettings().showPlayerStarting) {
|
||||
|
|
|
@ -27,7 +27,7 @@ public class RemoveTimeLimitAction {
|
|||
|
||||
public CompletableFuture<Boolean> execute() {
|
||||
source.setCursor(Cursor.WAIT);
|
||||
Instant unlimited = Instant.ofEpochMilli(Model.RECORD_INDEFINITELY);
|
||||
var unlimited = Instant.ofEpochMilli(Model.RECORD_INDEFINITELY);
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
selectedModel.setRecordUntil(unlimited);
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
package ctbrec.ui.action;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ctbrec.Model;
|
||||
import ctbrec.recorder.Recorder;
|
||||
import ctbrec.ui.controls.Dialogs;
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.Node;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class StartRecordingAction extends ModelMassEditAction {
|
||||
|
||||
public StartRecordingAction(Node source, List<? extends Model> models, Recorder recorder) {
|
||||
super(source, models);
|
||||
action = (m) -> {
|
||||
action = m -> {
|
||||
try {
|
||||
recorder.addModel(m);
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -11,8 +11,6 @@ import ctbrec.ui.AutosizeAlert;
|
|||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Alert;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.TextField;
|
||||
|
@ -36,7 +34,7 @@ public abstract class AbstractFileSelectionBox extends HBox {
|
|||
protected boolean allowEmptyValue = false;
|
||||
private Tooltip validationError = new Tooltip();
|
||||
|
||||
public AbstractFileSelectionBox() {
|
||||
protected AbstractFileSelectionBox() {
|
||||
super(5);
|
||||
fileInput = new TextField();
|
||||
fileInput.textProperty().addListener(textListener());
|
||||
|
@ -45,7 +43,7 @@ public abstract class AbstractFileSelectionBox extends HBox {
|
|||
validationError.hide();
|
||||
}
|
||||
});
|
||||
Node browse = createBrowseButton();
|
||||
var browse = createBrowseButton();
|
||||
browse.disableProperty().bind(disableProperty());
|
||||
fileInput.disableProperty().bind(disableProperty());
|
||||
fileInput.textProperty().bindBidirectional(fileProperty);
|
||||
|
@ -63,14 +61,14 @@ public abstract class AbstractFileSelectionBox extends HBox {
|
|||
});
|
||||
}
|
||||
|
||||
public AbstractFileSelectionBox(String initialValue) {
|
||||
protected AbstractFileSelectionBox(String initialValue) {
|
||||
this();
|
||||
fileInput.setText(initialValue);
|
||||
}
|
||||
|
||||
private ChangeListener<? super String> textListener() {
|
||||
return (obs, o, n) -> {
|
||||
String input = fileInput.getText();
|
||||
var input = fileInput.getText();
|
||||
if (StringUtil.isBlank(input)) {
|
||||
if (allowEmptyValue) {
|
||||
fileProperty.set("");
|
||||
|
@ -78,19 +76,19 @@ public abstract class AbstractFileSelectionBox extends HBox {
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
File program = new File(input);
|
||||
var program = new File(input);
|
||||
setFile(program);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected void setFile(File file) {
|
||||
String msg = validate(file);
|
||||
var msg = validate(file);
|
||||
if (msg != null) {
|
||||
fileInput.setBorder(new Border(new BorderStroke(Color.RED, BorderStrokeStyle.DASHED, new CornerRadii(2), new BorderWidths(2))));
|
||||
validationError.setText(msg);
|
||||
fileInput.setTooltip(validationError);
|
||||
Point2D p = fileInput.localToScreen(fileInput.getTranslateY(), fileInput.getTranslateY());
|
||||
var p = fileInput.localToScreen(fileInput.getTranslateY(), fileInput.getTranslateY());
|
||||
if (!validationError.isShowing() && getScene() != null) {
|
||||
validationError.show(getScene().getWindow(), p.getX(), p.getY() + fileInput.getHeight() + 4);
|
||||
}
|
||||
|
@ -123,7 +121,7 @@ public abstract class AbstractFileSelectionBox extends HBox {
|
|||
}
|
||||
|
||||
private Button createBrowseButton() {
|
||||
Button button = new Button("Select");
|
||||
var button = new Button("Select");
|
||||
button.setOnAction(e -> choose());
|
||||
button.prefHeightProperty().bind(this.heightProperty());
|
||||
button.prefWidthProperty().set(70);
|
||||
|
@ -131,14 +129,14 @@ public abstract class AbstractFileSelectionBox extends HBox {
|
|||
}
|
||||
|
||||
protected void choose() {
|
||||
FileChooser chooser = new FileChooser();
|
||||
File program = chooser.showOpenDialog(null);
|
||||
var chooser = new FileChooser();
|
||||
var program = chooser.showOpenDialog(null);
|
||||
if (program != null) {
|
||||
try {
|
||||
fileInput.setText(program.getCanonicalPath());
|
||||
} catch (IOException 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.setContentText("Couldn't determine path");
|
||||
alert.showAndWait();
|
||||
|
|
|
@ -19,8 +19,8 @@ public class DateTimeCellFactory<T> implements Callback<TableColumn<T, Instant>,
|
|||
if (empty || item == null) {
|
||||
setText("");
|
||||
} else {
|
||||
LocalDateTime dateTime = LocalDateTime.ofInstant(item, ZoneId.systemDefault());
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
|
||||
var dateTime = LocalDateTime.ofInstant(item, ZoneId.systemDefault());
|
||||
var formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
|
||||
String formattedDateTime = formatter.format(dateTime);
|
||||
setText(item.equals(Instant.EPOCH) ? "" : formattedDateTime);
|
||||
}
|
||||
|
|
|
@ -12,14 +12,14 @@ public class DirectorySelectionBox extends AbstractFileSelectionBox {
|
|||
|
||||
@Override
|
||||
protected void choose() {
|
||||
DirectoryChooser chooser = new DirectoryChooser();
|
||||
String preselection = Optional.ofNullable(fileProperty().get()).orElse(".");
|
||||
File currentDir = new File(preselection);
|
||||
var chooser = new DirectoryChooser();
|
||||
var preselection = Optional.ofNullable(fileProperty().get()).orElse(".");
|
||||
var currentDir = new File(preselection);
|
||||
if (currentDir.exists() && currentDir.isDirectory()) {
|
||||
chooser.setInitialDirectory(currentDir);
|
||||
}
|
||||
File selectedDir = chooser.showDialog(null);
|
||||
if(selectedDir != null) {
|
||||
if (selectedDir != null) {
|
||||
fileInput.setText(selectedDir.getAbsolutePath());
|
||||
setFile(selectedDir);
|
||||
}
|
||||
|
@ -27,12 +27,12 @@ public class DirectorySelectionBox extends AbstractFileSelectionBox {
|
|||
|
||||
@Override
|
||||
protected String validate(File file) {
|
||||
if(isDisabled()) {
|
||||
if (isDisabled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String msg = super.validate(file);
|
||||
if(msg != null) {
|
||||
if (msg != null) {
|
||||
return msg;
|
||||
} else if (!file.isDirectory()) {
|
||||
return "This is not a directory";
|
||||
|
|
|
@ -10,9 +10,9 @@ public class FasterVerticalScrollPaneSkin extends ScrollPaneSkin {
|
|||
super(scrollPane);
|
||||
|
||||
getSkinnable().addEventFilter(ScrollEvent.SCROLL, event -> {
|
||||
double ratio = scrollPane.getViewportBounds().getHeight() / scrollPane.getContent().getBoundsInLocal().getHeight();
|
||||
double baseUnitIncrement = 0.15;
|
||||
double unitIncrement = baseUnitIncrement * ratio * 1.25;
|
||||
var ratio = scrollPane.getViewportBounds().getHeight() / scrollPane.getContent().getBoundsInLocal().getHeight();
|
||||
var baseUnitIncrement = 0.15;
|
||||
var unitIncrement = baseUnitIncrement * ratio * 1.25;
|
||||
getVerticalScrollBar().setUnitIncrement(unitIncrement);
|
||||
|
||||
if (event.getDeltaX() < 0) {
|
||||
|
|
|
@ -12,12 +12,12 @@ public class FileSelectionBox extends AbstractFileSelectionBox {
|
|||
|
||||
@Override
|
||||
protected String validate(File file) {
|
||||
if(isDisabled()) {
|
||||
if (isDisabled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String msg = super.validate(file);
|
||||
if(msg != null) {
|
||||
if (msg != null) {
|
||||
return msg;
|
||||
} else if (!file.isFile()) {
|
||||
return "This is not a regular file";
|
||||
|
|
|
@ -46,10 +46,8 @@ import javafx.beans.property.SimpleDoubleProperty;
|
|||
import javafx.event.ActionEvent;
|
||||
import javafx.event.Event;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
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 Button leftButton = new Button("Left");
|
||||
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 Rectangle pagesClipRect = new Rectangle();
|
||||
private final Pane titlesPane = new Pane();
|
||||
|
@ -128,11 +126,6 @@ public class Popover extends Region implements EventHandler<Event>{
|
|||
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) {
|
||||
Page page = pages.isEmpty() ? null : pages.getFirst();
|
||||
if (page != null) {
|
||||
Node n = page.getPageNode();
|
||||
var n = page.getPageNode();
|
||||
if (n != null) {
|
||||
Insets insets = getInsets();
|
||||
var insets = getInsets();
|
||||
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) {
|
||||
Insets insets = getInsets();
|
||||
var insets = getInsets();
|
||||
return insets.getLeft() + 100 + insets.getRight();
|
||||
}
|
||||
|
||||
@Override protected double computePrefWidth(double height) {
|
||||
Page page = pages.isEmpty() ? null : pages.getFirst();
|
||||
if (page != null) {
|
||||
Node n = page.getPageNode();
|
||||
var n = page.getPageNode();
|
||||
if (n != null) {
|
||||
Insets insets = getInsets();
|
||||
var insets = getInsets();
|
||||
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 prefHeight = popoverHeight.get();
|
||||
if (prefHeight == -1) {
|
||||
Page page = pages.getFirst();
|
||||
var page = pages.getFirst();
|
||||
if (page != null) {
|
||||
Insets inset = getInsets();
|
||||
var inset = getInsets();
|
||||
if (width == -1) {
|
||||
width = prefWidth(-1);
|
||||
}
|
||||
|
@ -208,7 +201,7 @@ public class Popover extends Region implements EventHandler<Event>{
|
|||
}
|
||||
|
||||
@Override protected double computeMaxHeight(double width) {
|
||||
Scene scene = getScene();
|
||||
var scene = getScene();
|
||||
if (scene != null) {
|
||||
return scene.getHeight() - 100;
|
||||
} else {
|
||||
|
@ -220,14 +213,14 @@ public class Popover extends Region implements EventHandler<Event>{
|
|||
if (maxPopupHeight == -1) {
|
||||
maxPopupHeight = (int)getScene().getHeight()-100;
|
||||
}
|
||||
final Insets insets = getInsets();
|
||||
final var insets = getInsets();
|
||||
final int width = (int)getWidth();
|
||||
final int height = (int)getHeight();
|
||||
final int top = (int)insets.getTop() + 40;
|
||||
final int right = (int)insets.getRight();
|
||||
final int bottom = (int)insets.getBottom();
|
||||
final int left = (int)insets.getLeft();
|
||||
final int offset = 18;
|
||||
final var offset = 18;
|
||||
|
||||
int pageWidth = width - left - right;
|
||||
int pageHeight = height - top - bottom;
|
||||
|
@ -238,19 +231,18 @@ public class Popover extends Region implements EventHandler<Event>{
|
|||
pagesClipRect.setWidth(pageWidth);
|
||||
pagesClipRect.setHeight(pageHeight);
|
||||
|
||||
int pageX = 0;
|
||||
var pageX = 0;
|
||||
for (Node page : pagesPane.getChildren()) {
|
||||
page.resizeRelocate(pageX, 0, pageWidth, pageHeight);
|
||||
pageX += pageWidth + PAGE_GAP;
|
||||
}
|
||||
|
||||
int buttonHeight = (int)(leftButton.prefHeight(-1));
|
||||
if (buttonHeight < 30) buttonHeight = 30;
|
||||
final int buttonTop = (int)((top-buttonHeight)/2d);
|
||||
final int leftButtonWidth = (int)snapSizeX(leftButton.prefWidth(-1));
|
||||
leftButton.resizeRelocate(left, buttonTop + offset,leftButtonWidth,buttonHeight);
|
||||
final int rightButtonWidth = (int)snapSizeX(rightButton.prefWidth(-1));
|
||||
rightButton.resizeRelocate(width-right-rightButtonWidth, buttonTop + offset,rightButtonWidth,buttonHeight);
|
||||
int buttonHeight = Math.min(30, (int) (leftButton.prefHeight(-1)));
|
||||
final int buttonTop = (int) ((top - buttonHeight) / 2d);
|
||||
final int leftButtonWidth = (int) snapSizeX(leftButton.prefWidth(-1));
|
||||
leftButton.resizeRelocate(left, (double)buttonTop + offset, leftButtonWidth, buttonHeight);
|
||||
final int rightButtonWidth = (int) snapSizeX(rightButton.prefWidth(-1));
|
||||
rightButton.resizeRelocate(width - (double)right - rightButtonWidth, (double)buttonTop + offset, rightButtonWidth, buttonHeight);
|
||||
|
||||
if (title != null) {
|
||||
double tw = title.getWidth();
|
||||
|
@ -275,16 +267,16 @@ public class Popover extends Region implements EventHandler<Event>{
|
|||
}
|
||||
|
||||
public final void popPage() {
|
||||
Page oldPage = pages.pop();
|
||||
var oldPage = pages.pop();
|
||||
oldPage.handleHidden();
|
||||
oldPage.setPopover(null);
|
||||
Page page = pages.getFirst();
|
||||
var page = pages.getFirst();
|
||||
leftButton.setVisible(page.leftButtonText() != null);
|
||||
leftButton.setText(page.leftButtonText());
|
||||
rightButton.setVisible(page.rightButtonText() != null);
|
||||
rightButton.setText(page.rightButtonText());
|
||||
if (pages.size() > 0) {
|
||||
final Insets insets = getInsets();
|
||||
if (!pages.isEmpty()) {
|
||||
final var insets = getInsets();
|
||||
final int width = (int)prefWidth(-1);
|
||||
final int right = (int)insets.getRight();
|
||||
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) {
|
||||
final Node pageNode = page.getPageNode();
|
||||
final var pageNode = page.getPageNode();
|
||||
pageNode.setManaged(false);
|
||||
pagesPane.getChildren().add(pageNode);
|
||||
final Insets insets = getInsets();
|
||||
final var insets = getInsets();
|
||||
final int pageWidth = (int)(prefWidth(-1) - insets.getLeft() - insets.getRight());
|
||||
final int newPageX = (pageWidth + PAGE_GAP) * pages.size();
|
||||
leftButton.setVisible(page.leftButtonText() != null);
|
||||
|
@ -322,11 +314,11 @@ public class Popover extends Region implements EventHandler<Event>{
|
|||
title = new Label(page.getPageTitle());
|
||||
title.getStyleClass().add("popover-title");
|
||||
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);
|
||||
|
||||
if (!pages.isEmpty() && isVisible()) {
|
||||
final Timeline timeline = new Timeline(
|
||||
final var timeline = new Timeline(
|
||||
new KeyFrame(Duration.millis(350), (ActionEvent t) -> {
|
||||
pagesPane.setCache(false);
|
||||
resizePopoverToNewPage(pageNode);
|
||||
|
@ -344,7 +336,7 @@ public class Popover extends Region implements EventHandler<Event>{
|
|||
}
|
||||
|
||||
private void resizePopoverToNewPage(final Node newPageNode) {
|
||||
final Insets insets = getInsets();
|
||||
final var insets = getInsets();
|
||||
final double width = prefWidth(-1);
|
||||
final double contentWidth = width - insets.getLeft() - insets.getRight();
|
||||
double h = newPageNode.prefHeight(contentWidth);
|
||||
|
@ -366,7 +358,6 @@ public class Popover extends Region implements EventHandler<Event>{
|
|||
if (!isVisible() || fadeAnimation != null) {
|
||||
this.onHideCallback = onHideCallback;
|
||||
getScene().addEventFilter(MouseEvent.MOUSE_CLICKED, popoverHideHandler);
|
||||
// getScene().addEventFilter(ScrollEvent.ANY,popoverScrollHandler);
|
||||
|
||||
if (fadeAnimation != null) {
|
||||
fadeAnimation.stop();
|
||||
|
@ -376,17 +367,15 @@ public class Popover extends Region implements EventHandler<Event>{
|
|||
setVisible(true);
|
||||
}
|
||||
|
||||
FadeTransition fade = new FadeTransition(Duration.seconds(.1), this);
|
||||
var fade = new FadeTransition(Duration.seconds(.1), this);
|
||||
fade.setToValue(1.0);
|
||||
fade.setOnFinished((ActionEvent event) -> {
|
||||
fadeAnimation = null;
|
||||
});
|
||||
fade.setOnFinished((ActionEvent event) -> fadeAnimation = null);
|
||||
|
||||
ScaleTransition scale = new ScaleTransition(Duration.seconds(.1), this);
|
||||
var scale = new ScaleTransition(Duration.seconds(.1), this);
|
||||
scale.setToX(1);
|
||||
scale.setToY(1);
|
||||
|
||||
ParallelTransition tx = new ParallelTransition(fade, scale);
|
||||
var tx = new ParallelTransition(fade, scale);
|
||||
fadeAnimation = tx;
|
||||
tx.play();
|
||||
}
|
||||
|
@ -395,26 +384,24 @@ public class Popover extends Region implements EventHandler<Event>{
|
|||
public void hide(){
|
||||
if (isVisible() || fadeAnimation != null) {
|
||||
getScene().removeEventFilter(MouseEvent.MOUSE_CLICKED, popoverHideHandler);
|
||||
// getScene().removeEventFilter(ScrollEvent.ANY,popoverScrollHandler);
|
||||
|
||||
if (fadeAnimation != null) {
|
||||
fadeAnimation.stop();
|
||||
}
|
||||
|
||||
FadeTransition fade = new FadeTransition(Duration.seconds(.1), this);
|
||||
var fade = new FadeTransition(Duration.seconds(.1), this);
|
||||
fade.setToValue(0);
|
||||
fade.setOnFinished((ActionEvent event) -> {
|
||||
fadeAnimation = null;
|
||||
setVisible(false);
|
||||
//clearPages();
|
||||
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.setToY(.8);
|
||||
|
||||
ParallelTransition tx = new ParallelTransition(fade, scale);
|
||||
var tx = new ParallelTransition(fade, scale);
|
||||
fadeAnimation = tx;
|
||||
tx.play();
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ public class PopoverTreeList<T> extends ListView<T> implements Callback<ListView
|
|||
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 TreeItemListCell() {
|
||||
|
|
|
@ -12,12 +12,12 @@ public class ProgramSelectionBox extends FileSelectionBox {
|
|||
|
||||
@Override
|
||||
protected String validate(File file) {
|
||||
if(isDisabled()) {
|
||||
if (isDisabled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String msg = super.validate(file);
|
||||
if(msg != null) {
|
||||
if (msg != null) {
|
||||
return msg;
|
||||
} else if (!file.canExecute()) {
|
||||
return "This is not an executable application";
|
||||
|
|
|
@ -34,4 +34,3 @@ public class RecordingIndicator extends StackPane {
|
|||
icon.setImage(img);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,10 +44,10 @@ import javafx.scene.layout.Region;
|
|||
* Search field with styling and a clear button
|
||||
*/
|
||||
public class SearchBox extends TextField implements ChangeListener<String>{
|
||||
private static final int PREF_HEIGHT = 26;
|
||||
private final Button clearButton = new Button();
|
||||
private final Region innerBackground = new Region();
|
||||
private final Region icon = new Region();
|
||||
private final int prefHeight = 26;
|
||||
|
||||
public SearchBox() {
|
||||
getStyleClass().addAll("search-box");
|
||||
|
@ -55,7 +55,7 @@ public class SearchBox extends TextField implements ChangeListener<String>{
|
|||
innerBackground.getStyleClass().setAll("search-box-inner");
|
||||
setPromptText("Search");
|
||||
textProperty().addListener(this);
|
||||
setPrefHeight(prefHeight);
|
||||
setPrefHeight(PREF_HEIGHT);
|
||||
clearButton.getStyleClass().setAll("search-clear-button");
|
||||
clearButton.setCursor(Cursor.DEFAULT);
|
||||
clearButton.setOnMouseClicked((MouseEvent t) -> {
|
||||
|
@ -91,10 +91,10 @@ public class SearchBox extends TextField implements ChangeListener<String>{
|
|||
innerBackground.resize(getWidth(), getHeight());
|
||||
icon.setLayoutX(0);
|
||||
icon.setLayoutY(0);
|
||||
icon.resize(35,prefHeight);
|
||||
clearButton.setLayoutX(getWidth() - prefHeight);
|
||||
icon.resize(35,PREF_HEIGHT);
|
||||
clearButton.setLayoutX(getWidth() - PREF_HEIGHT);
|
||||
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) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package ctbrec.ui.controls.autocomplete;
|
||||
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
|
@ -36,18 +35,18 @@ public class AutoFillTextField extends TextField {
|
|||
|
||||
private void autocomplete(boolean fulltextSearch) {
|
||||
String oldtext = getOldText();
|
||||
if(oldtext.isEmpty()) {
|
||||
if (oldtext.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Optional<String> match = null;
|
||||
if(fulltextSearch) {
|
||||
Optional<String> match;
|
||||
if (fulltextSearch) {
|
||||
match = suggester.fulltext(oldtext);
|
||||
} else {
|
||||
match = suggester.startsWith(oldtext);
|
||||
}
|
||||
|
||||
if(match.isPresent()) {
|
||||
if (match.isPresent()) {
|
||||
setText(match.get());
|
||||
int pos = oldtext.length();
|
||||
positionCaret(pos);
|
||||
|
@ -56,7 +55,7 @@ public class AutoFillTextField extends TextField {
|
|||
}
|
||||
|
||||
private String getOldText() {
|
||||
if(getSelection().getLength() > 0) {
|
||||
if (getSelection().getLength() > 0) {
|
||||
return getText().substring(0, getSelection().getStart());
|
||||
} else {
|
||||
return getText();
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
package ctbrec.ui.controls.autocomplete;
|
||||
|
||||
public class Suggestion {
|
||||
|
||||
}
|
|
@ -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
|
||||
*/
|
||||
public void lowThumbDragged(double position) {
|
||||
T newPosition = getNewPosition(position);
|
||||
T high = getHigh();
|
||||
var newPosition = getNewPosition(position);
|
||||
var high = getHigh();
|
||||
if (newPosition.doubleValue() >= high.doubleValue()) {
|
||||
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
|
||||
*/
|
||||
public void highThumbDragged(double position) {
|
||||
T newPosition = getNewPosition(position);
|
||||
T low = getLow();
|
||||
var newPosition = getNewPosition(position);
|
||||
var low = getLow();
|
||||
if (newPosition.doubleValue() <= low.doubleValue()) {
|
||||
newPosition = getHigh();
|
||||
}
|
||||
|
@ -57,9 +57,9 @@ public class RangeSliderBehavior<T extends Number> extends BehaviorBase<RangeSli
|
|||
}
|
||||
|
||||
public void moveClosestThumbTo(double positionPercentage) {
|
||||
T newPosition = getNewPosition(positionPercentage);
|
||||
T low = getLow();
|
||||
T high = getHigh();
|
||||
var newPosition = getNewPosition(positionPercentage);
|
||||
var low = getLow();
|
||||
var high = getHigh();
|
||||
double distToLow = Math.abs(low.doubleValue() - newPosition.doubleValue());
|
||||
double distToHigh = Math.abs(high.doubleValue() - newPosition.doubleValue());
|
||||
if (distToLow < distToHigh) {
|
||||
|
|
|
@ -122,39 +122,39 @@ public class RangeSliderSkin extends SkinBase<RangeSlider<?>> {
|
|||
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 trackHeight = 5;// track.prefHeight(-1);
|
||||
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 radius = track.getBackground().getFills().isEmpty() ? 0 : track.getBackground().getFills().get(0).getRadii().getTopLeftHorizontalRadius();
|
||||
double trackRadius = track.getBackground() == null ? 0 : radius;
|
||||
|
||||
trackLength = w - thumbWidth;
|
||||
trackStart = x + (thumbWidth / 2);
|
||||
double tickLineHeight = (showTickMarks) ? tickLine.prefHeight(-1) : 0;
|
||||
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));
|
||||
lowThumbPos = (int) (startY + ((trackAreaHeight - thumbHeight) / 2));
|
||||
trackLength = w - thumbWidth;
|
||||
trackStart = x + (thumbWidth / 2);
|
||||
|
||||
// layout track
|
||||
track.resizeRelocate(trackStart - trackRadius, trackTop, trackLength + trackRadius + trackRadius, trackHeight);
|
||||
double trackTop = (int) (startY + ((trackAreaHeight - trackHeight) / 2));
|
||||
lowThumbPos = (int) (startY + ((trackAreaHeight - thumbHeight) / 2));
|
||||
|
||||
positionThumbs();
|
||||
// layout track
|
||||
track.resizeRelocate(trackStart - trackRadius, trackTop, trackLength + trackRadius + trackRadius, trackHeight);
|
||||
|
||||
if (showTickMarks) {
|
||||
tickLine.setLayoutX(trackStart);
|
||||
tickLine.setLayoutY(trackTop + trackHeight + TRACK_TO_TICK_GAP);
|
||||
tickLine.resize(trackLength, tickLineHeight);
|
||||
tickLine.requestAxisLayout();
|
||||
} else {
|
||||
if (tickLine != null) {
|
||||
tickLine.resize(0, 0);
|
||||
tickLine.requestAxisLayout();
|
||||
}
|
||||
tickLine = null;
|
||||
}
|
||||
positionThumbs();
|
||||
|
||||
if (showTickMarks) {
|
||||
tickLine.setLayoutX(trackStart);
|
||||
tickLine.setLayoutY(trackTop + trackHeight + TRACK_TO_TICK_GAP);
|
||||
tickLine.resize(trackLength, tickLineHeight);
|
||||
tickLine.requestAxisLayout();
|
||||
} else {
|
||||
if (tickLine != null) {
|
||||
tickLine.resize(0, 0);
|
||||
tickLine.requestAxisLayout();
|
||||
}
|
||||
tickLine = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void positionThumbs() {
|
||||
|
|
|
@ -23,13 +23,13 @@ public class PlaySound extends Action {
|
|||
|
||||
@Override
|
||||
public void accept(Event evt) {
|
||||
AudioClip clip = new AudioClip(url.toString());
|
||||
var clip = new AudioClip(url.toString());
|
||||
clip.play();
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ public class ShowNotification extends Action {
|
|||
|
||||
@Override
|
||||
public void accept(Event evt) {
|
||||
String header = evt.getType().toString();
|
||||
var header = evt.getType().toString();
|
||||
String msg;
|
||||
switch(evt.getType()) {
|
||||
case MODEL_STATUS_CHANGED:
|
||||
|
@ -25,7 +25,7 @@ public class ShowNotification extends Action {
|
|||
if (modelEvent.getOldState() == Model.State.UNKNOWN) {
|
||||
return;
|
||||
}
|
||||
Model m = modelEvent.getModel();
|
||||
var m = modelEvent.getModel();
|
||||
msg = m.getDisplayName() + " is now " + modelEvent.getNewState().toString();
|
||||
break;
|
||||
case RECORDING_STATUS_CHANGED:
|
||||
|
@ -41,5 +41,6 @@ public class ShowNotification extends Action {
|
|||
|
||||
@Override
|
||||
public void configure(ActionConfiguration config) throws Exception {
|
||||
// nothing to do here
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ import javafx.scene.control.ScrollPane;
|
|||
import javafx.scene.control.Tab;
|
||||
import javafx.scene.layout.VBox;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class NewsTab extends Tab implements TabSelectionListener {
|
||||
private static final String ACCESS_TOKEN = "a2804d73a89951a22e0f8483a6fcec8943afd88b7ba17c459c095aa9e6f94fd0";
|
||||
|
@ -44,14 +43,14 @@ public class NewsTab extends Tab implements TabSelectionListener {
|
|||
|
||||
private void loadToots() {
|
||||
try {
|
||||
Request request = new Request.Builder()
|
||||
var request = new Request.Builder()
|
||||
.url(URL)
|
||||
.header("Authorization", "Bearer " + ACCESS_TOKEN)
|
||||
.header(USER_AGENT, "ctbrec " + CamrecApplication.getVersion().toString())
|
||||
.build();
|
||||
try (Response response = CamrecApplication.httpClient.execute(request)) {
|
||||
try (var response = CamrecApplication.httpClient.execute(request)) {
|
||||
if (response.isSuccessful()) {
|
||||
String body = response.body().string();
|
||||
var body = response.body().string();
|
||||
if (body.startsWith("[")) {
|
||||
onSuccess(body);
|
||||
} else if (body.startsWith("{")) {
|
||||
|
@ -69,7 +68,7 @@ public class NewsTab extends Tab implements TabSelectionListener {
|
|||
}
|
||||
|
||||
private void onError(String body) throws IOException {
|
||||
JSONObject json = new JSONObject(body);
|
||||
var json = new JSONObject(body);
|
||||
if (json.has("error")) {
|
||||
throw new IOException("Request not successful: " + json.getString("error"));
|
||||
} else {
|
||||
|
@ -78,14 +77,14 @@ public class NewsTab extends Tab implements TabSelectionListener {
|
|||
}
|
||||
|
||||
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);
|
||||
Status[] statusArray = statusListAdapter.fromJson(body);
|
||||
Platform.runLater(() -> {
|
||||
layout.getChildren().clear();
|
||||
for (Status status : statusArray) {
|
||||
if (status.getInReplyToId() == null && !Objects.equals("direct", status.getVisibility())) {
|
||||
StatusPane stp = new StatusPane(status);
|
||||
var stp = new StatusPane(status);
|
||||
layout.getChildren().add(stp);
|
||||
VBox.setMargin(stp, new Insets(10));
|
||||
}
|
||||
|
|
|
@ -272,8 +272,8 @@ public class Status {
|
|||
|
||||
public ZonedDateTime getCreationTime() {
|
||||
String timestamp = getCreatedAt();
|
||||
Instant instant = Instant.parse(timestamp);
|
||||
ZonedDateTime time = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
|
||||
var instant = Instant.parse(timestamp);
|
||||
var time = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
|
||||
return time;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ public class StatusPane extends StackPane {
|
|||
|
||||
ZonedDateTime createdAt = status.getCreationTime();
|
||||
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.setOpacity(.7);
|
||||
time.setPadding(new Insets(3));
|
||||
|
@ -45,7 +45,7 @@ public class StatusPane extends StackPane {
|
|||
getChildren().add(time);
|
||||
StackPane.setMargin(time, new Insets(5, 5, 5, 10));
|
||||
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.widthProperty().bind(time.widthProperty());
|
||||
clip.setArcHeight(5);
|
||||
|
@ -53,7 +53,7 @@ public class StatusPane extends StackPane {
|
|||
time.setClip(clip);
|
||||
|
||||
reply = new Button("Reply");
|
||||
reply.setOnAction((evt) -> DesktopIntegration.open(status.getUrl()));
|
||||
reply.setOnAction(evt -> DesktopIntegration.open(status.getUrl()));
|
||||
getChildren().add(reply);
|
||||
StackPane.setMargin(reply, new Insets(5, 5, 5, 5));
|
||||
StackPane.setAlignment(reply, Pos.BOTTOM_RIGHT);
|
||||
|
@ -64,7 +64,7 @@ public class StatusPane extends StackPane {
|
|||
ObservableList<Node> childrenUnmodifiable = content.getChildrenUnmodifiable();
|
||||
for (Node node : childrenUnmodifiable) {
|
||||
if (node instanceof ScrollPane) {
|
||||
ScrollPane scrollPane = (ScrollPane) node;
|
||||
var scrollPane = (ScrollPane) node;
|
||||
Set<Node> nodes = scrollPane.lookupAll(".scroll-bar");
|
||||
for (final Node child : nodes) {
|
||||
if (child instanceof ScrollBar) {
|
||||
|
|
|
@ -47,13 +47,12 @@ public abstract class AbstractPostProcessingPaneFactory {
|
|||
}
|
||||
|
||||
class MapPreferencesStorage implements PreferencesStorage {
|
||||
|
||||
@Override
|
||||
public void save(Preferences preferences) throws IOException {
|
||||
for (Property<?> property : properties) {
|
||||
String key = property.getName();
|
||||
Object value = preferences.getSetting(key).get().getProperty().getValue();
|
||||
LOG.debug("{}={}", key, value.toString());
|
||||
LOG.debug("{}={}", key, value);
|
||||
pp.getConfig().put(key, value.toString());
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +63,7 @@ public abstract class AbstractPostProcessingPaneFactory {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Node createGui(Setting setting) throws Exception {
|
||||
public Node createGui(Setting setting) throws NoSuchFieldException, IllegalAccessException {
|
||||
Property<?> prop = setting.getProperty();
|
||||
if (prop instanceof ExclusiveSelectionProperty) {
|
||||
return createRadioGroup(setting);
|
||||
|
@ -86,109 +85,74 @@ public abstract class AbstractPostProcessingPaneFactory {
|
|||
return new Label("Unsupported Type for key " + setting.getKey() + ": " + setting.getProperty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Node createRadioGroup(Setting setting) {
|
||||
ExclusiveSelectionProperty prop = (ExclusiveSelectionProperty) setting.getProperty();
|
||||
ToggleGroup toggleGroup = new ToggleGroup();
|
||||
RadioButton optionA = new RadioButton(prop.getOptionA());
|
||||
optionA.setSelected(prop.getValue());
|
||||
optionA.setToggleGroup(toggleGroup);
|
||||
RadioButton optionB = new RadioButton(prop.getOptionB());
|
||||
optionB.setSelected(!optionA.isSelected());
|
||||
optionB.setToggleGroup(toggleGroup);
|
||||
optionA.selectedProperty().bindBidirectional(prop);
|
||||
HBox row = new HBox();
|
||||
row.getChildren().addAll(optionA, optionB);
|
||||
HBox.setMargin(optionA, new Insets(5));
|
||||
HBox.setMargin(optionB, new Insets(5));
|
||||
return row;
|
||||
}
|
||||
private Node createRadioGroup(Setting setting) {
|
||||
ExclusiveSelectionProperty prop = (ExclusiveSelectionProperty) setting.getProperty();
|
||||
var toggleGroup = new ToggleGroup();
|
||||
var optionA = new RadioButton(prop.getOptionA());
|
||||
optionA.setSelected(prop.getValue());
|
||||
optionA.setToggleGroup(toggleGroup);
|
||||
var optionB = new RadioButton(prop.getOptionB());
|
||||
optionB.setSelected(!optionA.isSelected());
|
||||
optionB.setToggleGroup(toggleGroup);
|
||||
optionA.selectedProperty().bindBidirectional(prop);
|
||||
var row = new HBox();
|
||||
row.getChildren().addAll(optionA, optionB);
|
||||
HBox.setMargin(optionA, new Insets(5));
|
||||
HBox.setMargin(optionB, new Insets(5));
|
||||
return row;
|
||||
}
|
||||
|
||||
private Node createFileSelector(Setting setting) {
|
||||
ProgramSelectionBox programSelector = new ProgramSelectionBox("");
|
||||
// programSelector.fileProperty().addListener((obs, o, n) -> saveValue(() -> {
|
||||
// String path = n;
|
||||
// Field field = Settings.class.getField(setting.getKey());
|
||||
// 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 createFileSelector(Setting setting) {
|
||||
var programSelector = new ProgramSelectionBox("");
|
||||
StringProperty property = (StringProperty) setting.getProperty();
|
||||
programSelector.fileProperty().bindBidirectional(property);
|
||||
return programSelector;
|
||||
}
|
||||
|
||||
private Node createDirectorySelector(Setting setting) {
|
||||
DirectorySelectionBox directorySelector = new DirectorySelectionBox("");
|
||||
directorySelector.prefWidth(400);
|
||||
// directorySelector.fileProperty().addListener((obs, o, n) -> saveValue(() -> {
|
||||
// String path = n;
|
||||
// Field field = Settings.class.getField(setting.getKey());
|
||||
// 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;
|
||||
}
|
||||
private Node createDirectorySelector(Setting setting) {
|
||||
var directorySelector = new DirectorySelectionBox("");
|
||||
directorySelector.prefWidth(400);
|
||||
StringProperty property = (StringProperty) setting.getProperty();
|
||||
directorySelector.fileProperty().bindBidirectional(property);
|
||||
return directorySelector;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Node createStringProperty(Setting setting) {
|
||||
TextField ctrl = new TextField();
|
||||
ctrl.textProperty().bindBidirectional(setting.getProperty());
|
||||
return ctrl;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
private Node createStringProperty(Setting setting) {
|
||||
var ctrl = new TextField();
|
||||
ctrl.textProperty().bindBidirectional(setting.getProperty());
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Node createIntegerProperty(Setting setting) {
|
||||
TextField ctrl = new TextField();
|
||||
Property<Number> prop = setting.getProperty();
|
||||
ctrl.textProperty().bindBidirectional(prop, new NumberStringConverter());
|
||||
return ctrl;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
private Node createIntegerProperty(Setting setting) {
|
||||
var ctrl = new TextField();
|
||||
Property<Number> prop = setting.getProperty();
|
||||
ctrl.textProperty().bindBidirectional(prop, new NumberStringConverter());
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Node createLongProperty(Setting setting) {
|
||||
TextField ctrl = new TextField();
|
||||
Property<Number> prop = setting.getProperty();
|
||||
ctrl.textProperty().bindBidirectional(prop, new NumberStringConverter());
|
||||
return ctrl;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
private Node createLongProperty(Setting setting) {
|
||||
var ctrl = new TextField();
|
||||
Property<Number> prop = setting.getProperty();
|
||||
ctrl.textProperty().bindBidirectional(prop, new NumberStringConverter());
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
private Node createBooleanProperty(Setting setting) {
|
||||
CheckBox ctrl = new CheckBox();
|
||||
BooleanProperty prop = (BooleanProperty) setting.getProperty();
|
||||
ctrl.selectedProperty().bindBidirectional(prop);
|
||||
return ctrl;
|
||||
}
|
||||
private Node createBooleanProperty(Setting setting) {
|
||||
var ctrl = new CheckBox();
|
||||
BooleanProperty prop = (BooleanProperty) setting.getProperty();
|
||||
ctrl.selectedProperty().bindBidirectional(prop);
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private Node createComboBox(Setting setting) throws NoSuchFieldException, IllegalAccessException {
|
||||
ListProperty<?> listProp = (ListProperty<?>) setting.getProperty();
|
||||
ComboBox<Object> comboBox = new ComboBox(listProp);
|
||||
// Field field = Settings.class.getField(setting.getKey());
|
||||
// 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;
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private Node createComboBox(Setting setting) {
|
||||
ListProperty<?> listProp = (ListProperty<?>) setting.getProperty();
|
||||
ComboBox<Object> comboBox = new ComboBox(listProp);
|
||||
return comboBox;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,24 +94,24 @@ public class ActionSettingsPanel extends GridPane {
|
|||
setVgap(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");
|
||||
add(headline, 0, 0);
|
||||
|
||||
actionTable = createActionTable();
|
||||
ScrollPane scrollPane = new ScrollPane(actionTable);
|
||||
var scrollPane = new ScrollPane(actionTable);
|
||||
scrollPane.setFitToHeight(true);
|
||||
scrollPane.setFitToWidth(true);
|
||||
scrollPane.setStyle("-fx-background-color: -fx-background");
|
||||
add(scrollPane, 0, 1);
|
||||
GridPane.setHgrow(scrollPane, Priority.ALWAYS);
|
||||
|
||||
Button add = new Button("Add");
|
||||
var add = new Button("Add");
|
||||
add.setOnAction(this::add);
|
||||
Button delete = new Button("Delete");
|
||||
var delete = new Button("Delete");
|
||||
delete.setOnAction(this::delete);
|
||||
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
|
||||
add(buttons, 0, 2);
|
||||
|
||||
|
@ -119,15 +119,15 @@ public class ActionSettingsPanel extends GridPane {
|
|||
}
|
||||
|
||||
private void add(ActionEvent evt) {
|
||||
Pane actionPane = createActionPane();
|
||||
Stage dialog = new Stage();
|
||||
var actionPane = createActionPane();
|
||||
var dialog = new Stage();
|
||||
dialog.initModality(Modality.APPLICATION_MODAL);
|
||||
dialog.initOwner(getScene().getWindow());
|
||||
dialog.setTitle("New Action");
|
||||
InputStream icon = getClass().getResourceAsStream("/icon.png");
|
||||
dialog.getIcons().add(new Image(icon));
|
||||
Wizard root = new Wizard(dialog, this::validateSettings, actionPane);
|
||||
Scene scene = new Scene(root, 800, 540);
|
||||
var root = new Wizard(dialog, this::validateSettings, actionPane);
|
||||
var scene = new Scene(root, 800, 540);
|
||||
scene.getStylesheets().addAll(getScene().getStylesheets());
|
||||
dialog.setScene(scene);
|
||||
centerOnParent(dialog);
|
||||
|
@ -138,58 +138,58 @@ public class ActionSettingsPanel extends GridPane {
|
|||
}
|
||||
|
||||
private void createEventHandler() {
|
||||
EventHandlerConfiguration config = new EventHandlerConfiguration();
|
||||
var config = new EventHandlerConfiguration();
|
||||
config.setName(name.getText());
|
||||
config.setEvent(event.getValue());
|
||||
if(event.getValue() == Event.Type.MODEL_STATUS_CHANGED) {
|
||||
PredicateConfiguration pc = new PredicateConfiguration();
|
||||
var pc = new PredicateConfiguration();
|
||||
pc.setType(ModelStatePredicate.class.getName());
|
||||
pc.getConfiguration().put("state", modelState.getValue().name());
|
||||
pc.setName("state = " + modelState.getValue().toString());
|
||||
config.getPredicates().add(pc);
|
||||
} else if(event.getValue() == Event.Type.RECORDING_STATUS_CHANGED) {
|
||||
PredicateConfiguration pc = new PredicateConfiguration();
|
||||
var pc = new PredicateConfiguration();
|
||||
pc.setType(RecordingStatePredicate.class.getName());
|
||||
pc.getConfiguration().put("state", recordingState.getValue().name());
|
||||
pc.setName("state = " + recordingState.getValue().toString());
|
||||
config.getPredicates().add(pc);
|
||||
} else if(event.getValue() == Event.Type.NO_SPACE_LEFT) {
|
||||
PredicateConfiguration pc = new PredicateConfiguration();
|
||||
var pc = new PredicateConfiguration();
|
||||
pc.setType(MatchAllPredicate.class.getName());
|
||||
pc.setName("no space left");
|
||||
config.getPredicates().add(pc);
|
||||
}
|
||||
if(!modelSelectionPane.isAllSelected()) {
|
||||
PredicateConfiguration pc = new PredicateConfiguration();
|
||||
var pc = new PredicateConfiguration();
|
||||
pc.setType(ModelPredicate.class.getName());
|
||||
pc.setModels(modelSelectionPane.getSelectedItems());
|
||||
pc.setName("model is one of:" + modelSelectionPane.getSelectedItems());
|
||||
config.getPredicates().add(pc);
|
||||
}
|
||||
if(showNotification.isSelected()) {
|
||||
ActionConfiguration ac = new ActionConfiguration();
|
||||
var ac = new ActionConfiguration();
|
||||
ac.setType(ShowNotification.class.getName());
|
||||
ac.setName("show notification");
|
||||
config.getActions().add(ac);
|
||||
}
|
||||
if(playSound.isSelected()) {
|
||||
ActionConfiguration ac = new ActionConfiguration();
|
||||
var ac = new ActionConfiguration();
|
||||
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.setName("play " + file.getName());
|
||||
config.getActions().add(ac);
|
||||
}
|
||||
if(executeProgram.isSelected()) {
|
||||
ActionConfiguration ac = new ActionConfiguration();
|
||||
var ac = new ActionConfiguration();
|
||||
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.setName("execute " + file.getName());
|
||||
config.getActions().add(ac);
|
||||
}
|
||||
|
||||
EventHandler handler = new EventHandler(config);
|
||||
var handler = new EventHandler(config);
|
||||
EventBusHolder.register(handler);
|
||||
Config.getInstance().getSettings().eventHandlers.add(config);
|
||||
actionTable.getItems().add(config);
|
||||
|
@ -229,7 +229,7 @@ public class ActionSettingsPanel extends GridPane {
|
|||
modelState.prefWidthProperty().bind(event.widthProperty());
|
||||
name.prefWidthProperty().bind(event.widthProperty());
|
||||
|
||||
int row = 0;
|
||||
var row = 0;
|
||||
layout.add(new Label("Name"), 0, row);
|
||||
layout.add(name, 1, row++);
|
||||
|
||||
|
@ -243,7 +243,7 @@ public class ActionSettingsPanel extends GridPane {
|
|||
layout.add(event, 1, row++);
|
||||
|
||||
event.getSelectionModel().selectedItemProperty().addListener((obs, oldV, newV) -> {
|
||||
boolean modelRelatedStuffDisabled = false;
|
||||
var modelRelatedStuffDisabled = false;
|
||||
if(newV == Event.Type.NO_SPACE_LEFT) {
|
||||
modelRelatedStuffDisabled = true;
|
||||
modelSelectionPane.selectAll();
|
||||
|
@ -265,7 +265,7 @@ public class ActionSettingsPanel extends GridPane {
|
|||
|
||||
layout.add(createSeparator(), 0, row++);
|
||||
|
||||
Label l = new Label("Models");
|
||||
var l = new Label("Models");
|
||||
layout.add(l, 0, row);
|
||||
modelSelectionPane = new ListSelectionPane<>(recorder.getModels(), Collections.emptyList());
|
||||
layout.add(modelSelectionPane, 1, row++);
|
||||
|
@ -278,8 +278,8 @@ public class ActionSettingsPanel extends GridPane {
|
|||
layout.add(showNotification, 0, row);
|
||||
layout.add(testNotification, 1, row++);
|
||||
testNotification.setOnAction(evt -> {
|
||||
DateTimeFormatter format = DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM);
|
||||
ZonedDateTime time = ZonedDateTime.now();
|
||||
var format = DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM);
|
||||
var time = ZonedDateTime.now();
|
||||
DesktopIntegration.notification(CamrecApplication.title, "Test Notification", "Oi, what's up! " + format.format(time));
|
||||
});
|
||||
testNotification.disableProperty().bind(showNotification.selectedProperty().not());
|
||||
|
@ -306,12 +306,12 @@ public class ActionSettingsPanel extends GridPane {
|
|||
}
|
||||
|
||||
private Node createSeparator() {
|
||||
Separator divider = new Separator(Orientation.HORIZONTAL);
|
||||
var divider = new Separator(Orientation.HORIZONTAL);
|
||||
GridPane.setHgrow(divider, Priority.ALWAYS);
|
||||
GridPane.setFillWidth(divider, true);
|
||||
GridPane.setColumnSpan(divider, 2);
|
||||
int tb = 20;
|
||||
int lr = 0;
|
||||
var tb = 20;
|
||||
var lr = 0;
|
||||
GridPane.setMargin(divider, new Insets(tb, lr, tb, lr));
|
||||
return divider;
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ public class ColorSettingsPane extends HBox {
|
|||
}
|
||||
|
||||
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.getGreen() * 255)));
|
||||
sb.append(toHex((int) (value.getBlue() * 255)));
|
||||
|
@ -72,7 +72,7 @@ public class ColorSettingsPane extends HBox {
|
|||
}
|
||||
|
||||
private CharSequence toHex(int v) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
if(v < 16) {
|
||||
sb.append('0');
|
||||
}
|
||||
|
|
|
@ -18,13 +18,13 @@ public class CreateContactSheetPaneFactory extends AbstractPostProcessingPaneFac
|
|||
|
||||
@Override
|
||||
public Preferences doCreatePostProcessorPane(PostProcessor pp) {
|
||||
SimpleStringProperty totalSize = new SimpleStringProperty(null, TOTAL_SIZE, pp.getConfig().getOrDefault(TOTAL_SIZE, "1920"));
|
||||
SimpleStringProperty padding = new SimpleStringProperty(null, PADDING, pp.getConfig().getOrDefault(PADDING, "4"));
|
||||
SimpleStringProperty cols = new SimpleStringProperty(null, COLS, pp.getConfig().getOrDefault(COLS, "8"));
|
||||
SimpleStringProperty rows = new SimpleStringProperty(null, ROWS, pp.getConfig().getOrDefault(ROWS, "7"));
|
||||
SimpleStringProperty filename = new SimpleStringProperty(null, FILENAME, pp.getConfig().getOrDefault(FILENAME, "contactsheet.jpg"));
|
||||
var totalSize = new SimpleStringProperty(null, TOTAL_SIZE, pp.getConfig().getOrDefault(TOTAL_SIZE, "1920"));
|
||||
var padding = new SimpleStringProperty(null, PADDING, pp.getConfig().getOrDefault(PADDING, "4"));
|
||||
var cols = new SimpleStringProperty(null, COLS, pp.getConfig().getOrDefault(COLS, "8"));
|
||||
var rows = new SimpleStringProperty(null, ROWS, pp.getConfig().getOrDefault(ROWS, "7"));
|
||||
var filename = new SimpleStringProperty(null, FILENAME, pp.getConfig().getOrDefault(FILENAME, "contactsheet.jpg"));
|
||||
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())));
|
||||
properties.add(totalSize);
|
||||
properties.add(padding);
|
||||
|
@ -34,8 +34,8 @@ public class CreateContactSheetPaneFactory extends AbstractPostProcessingPaneFac
|
|||
properties.add(background);
|
||||
properties.add(burnTimestamp);
|
||||
|
||||
Setting backgroundSetting = Setting.of("", background, "Hexadecimal value of the background color for the space between the thumbnails");
|
||||
Preferences prefs = Preferences.of(new MapPreferencesStorage(),
|
||||
var backgroundSetting = Setting.of("", background, "Hexadecimal value of the background color for the space between the thumbnails");
|
||||
var prefs = Preferences.of(new MapPreferencesStorage(),
|
||||
Category.of(pp.getName(),
|
||||
Setting.of("Total Width", totalSize, "Total width of the generated contact sheet"),
|
||||
Setting.of("Padding", padding, "Padding between the thumbnails"),
|
||||
|
@ -59,8 +59,8 @@ public class CreateContactSheetPaneFactory extends AbstractPostProcessingPaneFac
|
|||
}
|
||||
|
||||
private ColorPicker createColorPicker(String hexColor) {
|
||||
Color preselection = Color.web(hexColor);
|
||||
ColorPicker colorPicker = new ColorPicker(preselection);
|
||||
var preselection = Color.web(hexColor);
|
||||
var colorPicker = new ColorPicker(preselection);
|
||||
colorPicker.setOnAction(e -> background.set(colorPicker.getValue().toString()));
|
||||
return colorPicker;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package ctbrec.ui.settings;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
@ -71,55 +70,55 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Node createGui(Setting setting) throws Exception {
|
||||
config.disableSaving();
|
||||
try {
|
||||
Property<?> prop = setting.getProperty();
|
||||
if (prop instanceof ExclusiveSelectionProperty) {
|
||||
return createRadioGroup(setting);
|
||||
} else if (prop instanceof SimpleRangeProperty) {
|
||||
return createRangeSlider(setting);
|
||||
} else if (prop instanceof SimpleDirectoryProperty) {
|
||||
return createDirectorySelector(setting);
|
||||
} else if (prop instanceof SimpleFileProperty) {
|
||||
return createFileSelector(setting);
|
||||
} else if (prop instanceof IntegerProperty) {
|
||||
return createIntegerProperty(setting);
|
||||
} else if (prop instanceof LongProperty) {
|
||||
return createLongProperty(setting);
|
||||
} else if (prop instanceof BooleanProperty) {
|
||||
return createBooleanProperty(setting);
|
||||
} else if (prop instanceof ListProperty) {
|
||||
return createComboBox(setting);
|
||||
} else if (prop instanceof StringProperty) {
|
||||
return createStringProperty(setting);
|
||||
} else {
|
||||
return new Label("Unsupported Type for key " + setting.getKey() + ": " + setting.getProperty());
|
||||
}
|
||||
} finally {
|
||||
config.enableSaving();
|
||||
}
|
||||
public Node createGui(Setting setting) throws NoSuchFieldException, IllegalAccessException {
|
||||
config.disableSaving();
|
||||
try {
|
||||
Property<?> prop = setting.getProperty();
|
||||
if (prop instanceof ExclusiveSelectionProperty) {
|
||||
return createRadioGroup(setting);
|
||||
} else if (prop instanceof SimpleRangeProperty) {
|
||||
return createRangeSlider(setting);
|
||||
} else if (prop instanceof SimpleDirectoryProperty) {
|
||||
return createDirectorySelector(setting);
|
||||
} else if (prop instanceof SimpleFileProperty) {
|
||||
return createFileSelector(setting);
|
||||
} else if (prop instanceof IntegerProperty) {
|
||||
return createIntegerProperty(setting);
|
||||
} else if (prop instanceof LongProperty) {
|
||||
return createLongProperty(setting);
|
||||
} else if (prop instanceof BooleanProperty) {
|
||||
return createBooleanProperty(setting);
|
||||
} else if (prop instanceof ListProperty) {
|
||||
return createComboBox(setting);
|
||||
} else if (prop instanceof StringProperty) {
|
||||
return createStringProperty(setting);
|
||||
} else {
|
||||
return new Label("Unsupported Type for key " + setting.getKey() + ": " + setting.getProperty());
|
||||
}
|
||||
} finally {
|
||||
config.enableSaving();
|
||||
}
|
||||
}
|
||||
|
||||
private Node createRadioGroup(Setting setting) {
|
||||
ExclusiveSelectionProperty prop = (ExclusiveSelectionProperty) setting.getProperty();
|
||||
ToggleGroup toggleGroup = new ToggleGroup();
|
||||
RadioButton optionA = new RadioButton(prop.getOptionA());
|
||||
var toggleGroup = new ToggleGroup();
|
||||
var optionA = new RadioButton(prop.getOptionA());
|
||||
optionA.setSelected(prop.getValue());
|
||||
optionA.setToggleGroup(toggleGroup);
|
||||
RadioButton optionB = new RadioButton(prop.getOptionB());
|
||||
var optionB = new RadioButton(prop.getOptionB());
|
||||
optionB.setSelected(!optionA.isSelected());
|
||||
optionB.setToggleGroup(toggleGroup);
|
||||
optionA.selectedProperty().bindBidirectional(prop);
|
||||
prop.addListener((obs, oldV, newV) -> saveValue(() -> {
|
||||
Field field = Settings.class.getField(setting.getKey());
|
||||
field.set(settings, newV);
|
||||
var field = Settings.class.getField(setting.getKey());
|
||||
field.set(settings, newV); // NOSONAR
|
||||
if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) {
|
||||
runRestartRequiredCallback();
|
||||
}
|
||||
config.save();
|
||||
}));
|
||||
HBox row = new HBox();
|
||||
var row = new HBox();
|
||||
row.getChildren().addAll(optionA, optionB);
|
||||
HBox.setMargin(optionA, 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.getLow().addListener((obs, o, n) -> saveValue(() -> {
|
||||
int newV = labels.get(n.intValue());
|
||||
Field field = Settings.class.getField(rangeProperty.getLowKey());
|
||||
field.set(settings, newV);
|
||||
var field = Settings.class.getField(rangeProperty.getLowKey());
|
||||
field.set(settings, newV); // NOSONAR
|
||||
config.save();
|
||||
}));
|
||||
resolutionRange.getHigh().addListener((obs, o, n) -> saveValue(() -> {
|
||||
int newV = labels.get(n.intValue());
|
||||
Field field = Settings.class.getField(rangeProperty.getHighKey());
|
||||
field.set(settings, newV);
|
||||
var field = Settings.class.getField(rangeProperty.getHighKey());
|
||||
field.set(settings, newV); // NOSONAR
|
||||
config.save();
|
||||
}));
|
||||
return resolutionRange;
|
||||
}
|
||||
|
||||
private int getRangeSliderValue(List<Integer> values, List<Integer> labels, int value) {
|
||||
for (int i = 0; i < labels.size(); i++) {
|
||||
int label = labels.get(i).intValue();
|
||||
for (var i = 0; i < labels.size(); i++) {
|
||||
var label = labels.get(i).intValue();
|
||||
if (label == value) {
|
||||
return values.get(i);
|
||||
}
|
||||
|
@ -175,13 +174,13 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
|
|||
}
|
||||
|
||||
private Node createFileSelector(Setting setting) {
|
||||
ProgramSelectionBox programSelector = new ProgramSelectionBox("");
|
||||
var programSelector = new ProgramSelectionBox("");
|
||||
programSelector.fileProperty().addListener((obs, o, n) -> saveValue(() -> {
|
||||
String path = n;
|
||||
Field field = Settings.class.getField(setting.getKey());
|
||||
var field = Settings.class.getField(setting.getKey());
|
||||
String oldValue = (String) field.get(settings);
|
||||
if (!Objects.equals(path, oldValue)) {
|
||||
field.set(settings, path);
|
||||
field.set(settings, path); // NOSONAR
|
||||
if (setting.doesNeedRestart()) {
|
||||
runRestartRequiredCallback();
|
||||
}
|
||||
|
@ -194,14 +193,14 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
|
|||
}
|
||||
|
||||
private Node createDirectorySelector(Setting setting) {
|
||||
DirectorySelectionBox directorySelector = new DirectorySelectionBox("");
|
||||
var directorySelector = new DirectorySelectionBox("");
|
||||
directorySelector.prefWidth(400);
|
||||
directorySelector.fileProperty().addListener((obs, o, n) -> saveValue(() -> {
|
||||
String path = n;
|
||||
Field field = Settings.class.getField(setting.getKey());
|
||||
var field = Settings.class.getField(setting.getKey());
|
||||
String oldValue = (String) field.get(settings);
|
||||
if (!Objects.equals(path, oldValue)) {
|
||||
field.set(settings, path);
|
||||
field.set(settings, path); // NOSONAR
|
||||
if (setting.doesNeedRestart()) {
|
||||
runRestartRequiredCallback();
|
||||
}
|
||||
|
@ -214,10 +213,10 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
|
|||
}
|
||||
|
||||
private Node createStringProperty(Setting setting) {
|
||||
TextField ctrl = new TextField();
|
||||
var ctrl = new TextField();
|
||||
ctrl.textProperty().addListener((obs, oldV, newV) -> saveValue(() -> {
|
||||
Field field = Settings.class.getField(setting.getKey());
|
||||
field.set(settings, newV);
|
||||
var field = Settings.class.getField(setting.getKey());
|
||||
field.set(settings, newV); // NOSONAR
|
||||
if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) {
|
||||
runRestartRequiredCallback();
|
||||
}
|
||||
|
@ -230,14 +229,14 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Node createIntegerProperty(Setting setting) {
|
||||
TextField ctrl = new TextField();
|
||||
var ctrl = new TextField();
|
||||
ctrl.textProperty().addListener((obs, oldV, newV) -> saveValue(() -> {
|
||||
if (!newV.matches("\\d*")) {
|
||||
ctrl.setText(newV.replaceAll(PATTERN_NOT_A_DIGIT, ""));
|
||||
}
|
||||
if (!ctrl.getText().isEmpty()) {
|
||||
Field field = Settings.class.getField(setting.getKey());
|
||||
field.set(settings, Integer.parseInt(ctrl.getText()));
|
||||
var field = Settings.class.getField(setting.getKey());
|
||||
field.set(settings, Integer.parseInt(ctrl.getText())); // NOSONAR
|
||||
if (setting.doesNeedRestart() && !Objects.equals(oldV, newV) && prefs != null) {
|
||||
runRestartRequiredCallback();
|
||||
}
|
||||
|
@ -251,18 +250,18 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Node createLongProperty(Setting setting) {
|
||||
TextField ctrl = new TextField();
|
||||
var ctrl = new TextField();
|
||||
ctrl.textProperty().addListener((obs, oldV, newV) -> saveValue(() -> {
|
||||
if (!newV.matches("\\d*")) {
|
||||
ctrl.setText(newV.replaceAll(PATTERN_NOT_A_DIGIT, ""));
|
||||
}
|
||||
if (!ctrl.getText().isEmpty()) {
|
||||
long value = Long.parseLong(ctrl.getText());
|
||||
var value = Long.parseLong(ctrl.getText());
|
||||
if (setting.getConverter() != null) {
|
||||
value = (long) setting.getConverter().convertFrom(value);
|
||||
}
|
||||
Field field = Settings.class.getField(setting.getKey());
|
||||
field.set(settings, value);
|
||||
var field = Settings.class.getField(setting.getKey());
|
||||
field.set(settings, value); // NOSONAR
|
||||
if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) {
|
||||
runRestartRequiredCallback();
|
||||
}
|
||||
|
@ -275,10 +274,10 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
|
|||
}
|
||||
|
||||
private Node createBooleanProperty(Setting setting) {
|
||||
CheckBox ctrl = new CheckBox();
|
||||
var ctrl = new CheckBox();
|
||||
ctrl.selectedProperty().addListener((obs, oldV, newV) -> saveValue(() -> {
|
||||
Field field = Settings.class.getField(setting.getKey());
|
||||
field.set(settings, newV);
|
||||
var field = Settings.class.getField(setting.getKey());
|
||||
field.set(settings, newV); // NOSONAR
|
||||
if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) {
|
||||
runRestartRequiredCallback();
|
||||
}
|
||||
|
@ -293,7 +292,7 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
|
|||
private Node createComboBox(Setting setting) throws NoSuchFieldException, IllegalAccessException {
|
||||
ListProperty<?> listProp = (ListProperty<?>) setting.getProperty();
|
||||
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);
|
||||
if (StringUtil.isNotBlank(value.toString())) {
|
||||
if (setting.getConverter() != null) {
|
||||
|
@ -305,9 +304,9 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
|
|||
comboBox.valueProperty().addListener((obs, oldV, newV) -> saveValue(() -> {
|
||||
LOG.debug("Saving setting {}", setting.getKey());
|
||||
if (setting.getConverter() != null) {
|
||||
field.set(settings, setting.getConverter().convertFrom(newV));
|
||||
field.set(settings, setting.getConverter().convertFrom(newV)); // NOSONAR
|
||||
} else {
|
||||
field.set(settings, newV);
|
||||
field.set(settings, newV); // NOSONAR
|
||||
}
|
||||
if (setting.doesNeedRestart() && !Objects.equals(oldV, newV)) {
|
||||
runRestartRequiredCallback();
|
||||
|
@ -330,6 +329,6 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
|
|||
|
||||
@FunctionalInterface
|
||||
private interface Exec {
|
||||
public void run() throws Exception;
|
||||
public void run() throws IllegalAccessException, IOException, NoSuchFieldException;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ public class DeleteTooShortPaneFactory extends AbstractPostProcessingPaneFactory
|
|||
|
||||
@Override
|
||||
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);
|
||||
|
||||
return Preferences.of(new MapPreferencesStorage(),
|
||||
|
|
|
@ -2,7 +2,6 @@ package ctbrec.ui.settings;
|
|||
|
||||
import static javafx.scene.control.ButtonType.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
|
@ -57,7 +56,7 @@ public class IgnoreList extends GridPane {
|
|||
setVgap(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");
|
||||
add(headline, 0, 0);
|
||||
|
||||
|
@ -71,13 +70,13 @@ public class IgnoreList extends GridPane {
|
|||
add(ignoreListView, 0, 1);
|
||||
GridPane.setHgrow(ignoreListView, Priority.ALWAYS);
|
||||
|
||||
Button remove = new Button("Remove");
|
||||
var remove = new Button("Remove");
|
||||
remove.setOnAction(evt -> removeSelectedModels());
|
||||
Button exportIgnoreList = new Button("Export");
|
||||
var exportIgnoreList = new Button("Export");
|
||||
exportIgnoreList.setOnAction(e -> exportIgnoreList());
|
||||
Button importIgnoreList = new Button("Import");
|
||||
var importIgnoreList = new Button("Import");
|
||||
importIgnoreList.setOnAction(e -> importIgnoreList());
|
||||
HBox buttons = new HBox(10, remove, exportIgnoreList, importIgnoreList);
|
||||
var buttons = new HBox(10, remove, exportIgnoreList, importIgnoreList);
|
||||
add(buttons, 0, 2);
|
||||
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() {
|
||||
List<String> selectedModels = ignoreListView.getSelectionModel().getSelectedItems();
|
||||
if (selectedModels.isEmpty()) {
|
||||
return;
|
||||
return; // NOSONAR
|
||||
} else {
|
||||
Config.getInstance().getSettings().ignoredModels.removeAll(selectedModels);
|
||||
ignoreListView.getItems().removeAll(selectedModels);
|
||||
|
@ -110,16 +109,16 @@ public class IgnoreList extends GridPane {
|
|||
}
|
||||
|
||||
private void exportIgnoreList() {
|
||||
FileChooser chooser = new FileChooser();
|
||||
var chooser = new FileChooser();
|
||||
chooser.setTitle("Export ignore list");
|
||||
chooser.setInitialFileName("ctbrec-ignorelist.json");
|
||||
File file = chooser.showSaveDialog(null);
|
||||
var file = chooser.showSaveDialog(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);
|
||||
JsonAdapter<List<String>> adapter = moshi.adapter(modelListType);
|
||||
adapter = adapter.indent(" ");
|
||||
try (FileOutputStream out = new FileOutputStream(file)) {
|
||||
try (var out = new FileOutputStream(file)) {
|
||||
String json = adapter.toJson(Config.getInstance().getSettings().ignoredModels);
|
||||
out.write(json.getBytes(StandardCharsets.UTF_8));
|
||||
} catch (IOException e) {
|
||||
|
@ -129,20 +128,20 @@ public class IgnoreList extends GridPane {
|
|||
}
|
||||
|
||||
private void importIgnoreList() {
|
||||
FileChooser chooser = new FileChooser();
|
||||
var chooser = new FileChooser();
|
||||
chooser.setTitle("Import ignore list");
|
||||
File file = chooser.showOpenDialog(null);
|
||||
var file = chooser.showOpenDialog(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);
|
||||
JsonAdapter<List<String>> adapter = moshi.adapter(modelListType);
|
||||
try {
|
||||
byte[] fileContent = Files.readAllBytes(file.toPath());
|
||||
List<String> ignoredModels = adapter.fromJson(new String(fileContent, StandardCharsets.UTF_8));
|
||||
boolean confirmed = true;
|
||||
var confirmed = true;
|
||||
if (!Config.getInstance().getSettings().ignoredModels.isEmpty()) {
|
||||
String msg = "This will replace the existing ignore list! Continue?";
|
||||
AutosizeAlert confirm = new AutosizeAlert(AlertType.CONFIRMATION, msg, getScene(), YES, NO);
|
||||
var msg = "This will replace the existing ignore list! Continue?";
|
||||
var confirm = new AutosizeAlert(AlertType.CONFIRMATION, msg, getScene(), YES, NO);
|
||||
confirm.setTitle("Import ignore list");
|
||||
confirm.setHeaderText("Overwrite ignore list");
|
||||
confirm.showAndWait();
|
||||
|
|
|
@ -38,7 +38,7 @@ public class ListSelectionPane<T extends Comparable<T>> extends GridPane {
|
|||
ObservableList<T> obsAvail = FXCollections.observableArrayList(available);
|
||||
ObservableList<T> obsSel = FXCollections.observableArrayList(selected);
|
||||
for (Iterator<T> iterator = obsAvail.iterator(); iterator.hasNext();) {
|
||||
T t = iterator.next();
|
||||
var t = iterator.next();
|
||||
if(obsSel.contains(t)) {
|
||||
iterator.remove();
|
||||
}
|
||||
|
@ -52,13 +52,13 @@ public class ListSelectionPane<T extends Comparable<T>> extends GridPane {
|
|||
}
|
||||
|
||||
private void createGui() {
|
||||
Label labelAvailable = new Label("Available");
|
||||
Label labelSelected = new Label("Selected");
|
||||
var labelAvailable = new Label("Available");
|
||||
var labelSelected = new Label("Selected");
|
||||
|
||||
add(labelAvailable, 0, 0);
|
||||
add(availableListView, 0, 1);
|
||||
|
||||
VBox buttonBox = new VBox(5);
|
||||
var buttonBox = new VBox(5);
|
||||
buttonBox.getChildren().add(addModel);
|
||||
buttonBox.getChildren().add(removeModel);
|
||||
buttonBox.setAlignment(Pos.CENTER);
|
||||
|
|
|
@ -11,7 +11,7 @@ public class MoverPaneFactory extends AbstractPostProcessingPaneFactory {
|
|||
|
||||
@Override
|
||||
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);
|
||||
|
||||
return Preferences.of(new MapPreferencesStorage(),
|
||||
|
|
|
@ -1,7 +1,21 @@
|
|||
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.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 javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
|
@ -16,25 +30,20 @@ import javafx.scene.layout.Priority;
|
|||
import javafx.scene.layout.VBox;
|
||||
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 {
|
||||
|
||||
private final Config config;
|
||||
|
||||
private static final Class<?>[] POST_PROCESSOR_CLASSES = new Class<?>[]{ // @formatter: off
|
||||
Copy.class,
|
||||
Rename.class,
|
||||
Move.class,
|
||||
Remux.class,
|
||||
Script.class,
|
||||
DeleteOriginal.class,
|
||||
DeleteTooShort.class,
|
||||
RemoveKeepFile.class,
|
||||
CreateContactSheet.class
|
||||
Copy.class,
|
||||
Rename.class,
|
||||
Move.class,
|
||||
Remux.class,
|
||||
Script.class,
|
||||
DeleteOriginal.class,
|
||||
DeleteTooShort.class,
|
||||
RemoveKeepFile.class,
|
||||
CreateContactSheet.class
|
||||
}; // @formatter: on
|
||||
|
||||
ListView<PostProcessor> stepListView;
|
||||
|
@ -61,7 +70,7 @@ public class PostProcessingStepPanel extends GridPane {
|
|||
add = createAddButton();
|
||||
remove = createRemoveButton();
|
||||
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.addListener((ListChangeListener<PostProcessor>) change -> {
|
||||
|
@ -78,7 +87,7 @@ public class PostProcessingStepPanel extends GridPane {
|
|||
add(buttons, 1, 0);
|
||||
|
||||
stepListView.getSelectionModel().selectedIndexProperty().addListener((obs, oldV, newV) -> {
|
||||
int idx = newV.intValue();
|
||||
var idx = newV.intValue();
|
||||
boolean noSelection = idx == -1;
|
||||
up.setDisable(noSelection || idx == 0);
|
||||
down.setDisable(noSelection || idx == stepList.size() - 1);
|
||||
|
@ -88,7 +97,7 @@ public class PostProcessingStepPanel extends GridPane {
|
|||
}
|
||||
|
||||
private Button createUpButton() {
|
||||
Button button = createButton("\u25B4", "Move step up");
|
||||
var button = createButton("\u25B4", "Move step up");
|
||||
button.setOnAction(evt -> {
|
||||
int idx = stepListView.getSelectionModel().getSelectedIndex();
|
||||
PostProcessor selectedItem = stepListView.getSelectionModel().getSelectedItem();
|
||||
|
@ -100,7 +109,7 @@ public class PostProcessingStepPanel extends GridPane {
|
|||
}
|
||||
|
||||
private Button createDownButton() {
|
||||
Button button = createButton("\u25BE", "Move step down");
|
||||
var button = createButton("\u25BE", "Move step down");
|
||||
button.setOnAction(evt -> {
|
||||
int idx = stepListView.getSelectionModel().getSelectedIndex();
|
||||
PostProcessor selectedItem = stepListView.getSelectionModel().getSelectedItem();
|
||||
|
@ -112,7 +121,7 @@ public class PostProcessingStepPanel extends GridPane {
|
|||
}
|
||||
|
||||
private Button createAddButton() {
|
||||
Button button = createButton("+", "Add a new step");
|
||||
var button = createButton("+", "Add a new step");
|
||||
button.setDisable(false);
|
||||
button.setOnAction(evt -> {
|
||||
PostProcessor[] options = createOptions();
|
||||
|
@ -122,7 +131,7 @@ public class PostProcessingStepPanel extends GridPane {
|
|||
choice.setResizable(true);
|
||||
choice.setWidth(600);
|
||||
choice.getDialogPane().setMinWidth(400);
|
||||
Stage stage = (Stage) choice.getDialogPane().getScene().getWindow();
|
||||
var stage = (Stage) choice.getDialogPane().getScene().getWindow();
|
||||
stage.getScene().getStylesheets().addAll(getScene().getStylesheets());
|
||||
InputStream icon = Dialogs.class.getResourceAsStream("/icon.png");
|
||||
stage.getIcons().add(new Image(icon));
|
||||
|
@ -144,8 +153,8 @@ public class PostProcessingStepPanel extends GridPane {
|
|||
|
||||
private PostProcessor[] createOptions() {
|
||||
try {
|
||||
PostProcessor[] options = new PostProcessor[POST_PROCESSOR_CLASSES.length];
|
||||
for (int i = 0; i < POST_PROCESSOR_CLASSES.length; i++) {
|
||||
var options = new PostProcessor[POST_PROCESSOR_CLASSES.length];
|
||||
for (var i = 0; i < POST_PROCESSOR_CLASSES.length; i++) {
|
||||
Class<?> cls = POST_PROCESSOR_CLASSES[i];
|
||||
PostProcessor pp;
|
||||
pp = (PostProcessor) cls.getDeclaredConstructor().newInstance();
|
||||
|
@ -160,7 +169,7 @@ public class PostProcessingStepPanel extends GridPane {
|
|||
}
|
||||
|
||||
private Button createRemoveButton() {
|
||||
Button button = createButton("-", "Remove selected step");
|
||||
var button = createButton("-", "Remove selected step");
|
||||
button.setOnAction(evt -> {
|
||||
PostProcessor selectedItem = stepListView.getSelectionModel().getSelectedItem();
|
||||
if (selectedItem != null) {
|
||||
|
@ -171,7 +180,7 @@ public class PostProcessingStepPanel extends GridPane {
|
|||
}
|
||||
|
||||
private Button createEditButton() {
|
||||
Button button = createButton("\u270E", "Edit selected step");
|
||||
var button = createButton("\u270E", "Edit selected step");
|
||||
button.setOnAction(evt -> {
|
||||
PostProcessor selectedItem = stepListView.getSelectionModel().getSelectedItem();
|
||||
PostProcessingDialogFactory.openEditDialog(selectedItem, getScene(), stepList);
|
||||
|
@ -182,7 +191,7 @@ public class PostProcessingStepPanel extends GridPane {
|
|||
}
|
||||
|
||||
private Button createButton(String text, String tooltip) {
|
||||
Button b = new Button(text);
|
||||
var b = new Button(text);
|
||||
b.setTooltip(new Tooltip(tooltip));
|
||||
b.setDisable(true);
|
||||
b.setPrefSize(32, 32);
|
||||
|
|
|
@ -11,8 +11,8 @@ public class RemuxerPaneFactory extends AbstractPostProcessingPaneFactory {
|
|||
|
||||
@Override
|
||||
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"));
|
||||
SimpleStringProperty fileExt = new SimpleStringProperty(null, Remux.FILE_EXT, pp.getConfig().getOrDefault(Remux.FILE_EXT, "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"));
|
||||
var fileExt = new SimpleStringProperty(null, Remux.FILE_EXT, pp.getConfig().getOrDefault(Remux.FILE_EXT, "mp4"));
|
||||
properties.add(ffmpegParams);
|
||||
properties.add(fileExt);
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ public class RenamerPaneFactory extends AbstractPostProcessingPaneFactory {
|
|||
|
||||
@Override
|
||||
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);
|
||||
|
||||
return Preferences.of(new MapPreferencesStorage(),
|
||||
|
|
|
@ -11,8 +11,8 @@ public class ScriptPaneFactory extends AbstractPostProcessingPaneFactory {
|
|||
|
||||
@Override
|
||||
public Preferences doCreatePostProcessorPane(PostProcessor pp) {
|
||||
SimpleStringProperty 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 script = new SimpleStringProperty(null, Script.SCRIPT_EXECUTABLE, pp.getConfig().getOrDefault(Script.SCRIPT_EXECUTABLE, "c:\\users\\johndoe\\somescript"));
|
||||
var params = new SimpleStringProperty(null, Script.SCRIPT_PARAMS, pp.getConfig().getOrDefault(Script.SCRIPT_PARAMS, "${absolutePath}"));
|
||||
properties.add(script);
|
||||
properties.add(params);
|
||||
|
||||
|
|
|
@ -203,8 +203,8 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
}
|
||||
|
||||
private void createGui() {
|
||||
PostProcessingStepPanel postProcessingStepPanel = new PostProcessingStepPanel(config);
|
||||
Button variablesHelpButton = createHelpButton("Variables", "http://localhost:5689/docs/PostProcessing.md#variables");
|
||||
var postProcessingStepPanel = new PostProcessingStepPanel(config);
|
||||
var variablesHelpButton = createHelpButton("Variables", "http://localhost:5689/docs/PostProcessing.md#variables");
|
||||
ignoreList = new IgnoreList(sites);
|
||||
List<Category> siteCategories = new ArrayList<>();
|
||||
for (Site site : sites) {
|
||||
|
@ -212,8 +212,8 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
.ifPresent(configPanel -> siteCategories.add(Category.of(site.getName(), configPanel)));
|
||||
}
|
||||
|
||||
CtbrecPreferencesStorage storage = new CtbrecPreferencesStorage(config);
|
||||
Preferences prefs = Preferences.of(storage,
|
||||
var storage = new CtbrecPreferencesStorage(config);
|
||||
var prefs = Preferences.of(storage,
|
||||
Category.of("General",
|
||||
Group.of("General",
|
||||
Setting.of("User-Agent", httpUserAgent),
|
||||
|
@ -304,15 +304,15 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
storage.setPreferences(prefs);
|
||||
preferencesView.setMinSize(800, 400);
|
||||
preferencesView.setPrefSize(1280, 960);
|
||||
ScrollPane scrollPane = new ScrollPane(preferencesView);
|
||||
GridPane container = new GridPane();
|
||||
var scrollPane = new ScrollPane(preferencesView);
|
||||
var container = new GridPane();
|
||||
container.add(scrollPane, 0, 0);
|
||||
GridPane.setFillWidth(scrollPane, true);
|
||||
GridPane.setFillHeight(scrollPane, true);
|
||||
GridPane.setHgrow(scrollPane, Priority.ALWAYS);
|
||||
GridPane.setVgrow(scrollPane, Priority.ALWAYS);
|
||||
|
||||
StackPane stackPane = new StackPane();
|
||||
var stackPane = new StackPane();
|
||||
stackPane.getChildren().add(container);
|
||||
restartNotification = new Label("Restart Required");
|
||||
restartNotification.setVisible(false);
|
||||
|
@ -369,7 +369,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
}
|
||||
|
||||
private Button createHelpButton(String text, String url) {
|
||||
Button postProcessingHelpButton = new Button(text);
|
||||
var postProcessingHelpButton = new Button(text);
|
||||
postProcessingHelpButton.setOnAction(e -> {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
|
@ -446,7 +446,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
Config.getInstance().getSettings().key = key;
|
||||
saveConfig();
|
||||
}
|
||||
TextInputDialog keyDialog = new TextInputDialog();
|
||||
var keyDialog = new TextInputDialog();
|
||||
keyDialog.setResizable(true);
|
||||
keyDialog.setTitle("Server Authentication");
|
||||
keyDialog.setHeaderText("A key has been generated");
|
||||
|
@ -485,7 +485,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
}
|
||||
|
||||
public static GridPane createGridLayout() {
|
||||
GridPane layout = new GridPane();
|
||||
var layout = new GridPane();
|
||||
layout.setPadding(new Insets(10));
|
||||
layout.setHgap(5);
|
||||
layout.setVgap(5);
|
||||
|
@ -500,7 +500,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
fadeIn.setOnFinished(e -> {
|
||||
Transition fadeOut = changeOpacity(restartNotification, 0);
|
||||
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.play();
|
||||
});
|
||||
|
@ -509,7 +509,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
|
||||
private static final Duration ANIMATION_DURATION = new Duration(500);
|
||||
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.setToValue(opacity);
|
||||
return transition;
|
||||
|
@ -536,8 +536,8 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
final var prime = 31;
|
||||
var result = 1;
|
||||
result = prime * result + value;
|
||||
return result;
|
||||
}
|
||||
|
@ -590,8 +590,8 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
final var prime = 31;
|
||||
var result = 1;
|
||||
result = prime * result + (int) (value ^ (value >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -90,17 +90,17 @@ public class Category {
|
|||
String q = filter.toLowerCase().trim();
|
||||
if(hasGroups() || hasSubCategories()) {
|
||||
return name.toLowerCase().contains(q)
|
||||
| groupsContains(q)
|
||||
| subCategoriesContains(q);
|
||||
|| groupsContains(q)
|
||||
|| subCategoriesContains(q);
|
||||
} else {
|
||||
return name.toLowerCase().contains(q)
|
||||
| guiContains(q);
|
||||
|| guiContains(q);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean subCategoriesContains(String filter) {
|
||||
boolean contains = false;
|
||||
var contains = false;
|
||||
if (subCategories != null) {
|
||||
for (Category category : subCategories) {
|
||||
if (category.contains(filter)) {
|
||||
|
@ -112,7 +112,7 @@ public class Category {
|
|||
}
|
||||
|
||||
private boolean groupsContains(String filter) {
|
||||
boolean contains = false;
|
||||
var contains = false;
|
||||
if (groups != null) {
|
||||
for (Group group : groups) {
|
||||
if (group.contains(filter)) {
|
||||
|
@ -131,9 +131,9 @@ public class Category {
|
|||
}
|
||||
|
||||
private boolean nodeContains(Node node, String filter) {
|
||||
boolean contains = false;
|
||||
var contains = false;
|
||||
if (node instanceof Pane) {
|
||||
Pane pane = (Pane) node;
|
||||
var pane = (Pane) node;
|
||||
for (Node child : pane.getChildren()) {
|
||||
contains |= nodeContains(child, filter);
|
||||
}
|
||||
|
|
|
@ -34,11 +34,11 @@ public class Group {
|
|||
}
|
||||
|
||||
public boolean contains(String filter) {
|
||||
return name.toLowerCase().contains(filter) | settingsContain(filter);
|
||||
return name.toLowerCase().contains(filter) || settingsContain(filter);
|
||||
}
|
||||
|
||||
private boolean settingsContain(String filter) {
|
||||
boolean contains = false;
|
||||
var contains = false;
|
||||
if (settings != null) {
|
||||
for (Setting setting : settings) {
|
||||
if (setting.contains(filter)) {
|
||||
|
|
|
@ -16,7 +16,7 @@ class HighlightingSupport {
|
|||
private HighlightingSupport() {}
|
||||
|
||||
static void highlightMatches(Category cat, String filter) {
|
||||
Node node = cat.getGuiOrElse(Label::new);
|
||||
var node = cat.getGuiOrElse(Label::new);
|
||||
highlightMatchess(node, filter);
|
||||
if(cat.hasSubCategories()) {
|
||||
for (Category sub : cat.getSubCategories()) {
|
||||
|
@ -26,9 +26,9 @@ class HighlightingSupport {
|
|||
}
|
||||
|
||||
static void highlightMatchess(Node node, String filter) {
|
||||
boolean contains = false;
|
||||
var contains = false;
|
||||
if (node instanceof Pane) {
|
||||
Pane pane = (Pane) node;
|
||||
var pane = (Pane) node;
|
||||
for (Node child : pane.getChildren()) {
|
||||
highlightMatchess(child, filter);
|
||||
}
|
||||
|
@ -51,9 +51,9 @@ class HighlightingSupport {
|
|||
}
|
||||
|
||||
private static boolean labelControlContains(Label lbl, String filter) {
|
||||
boolean contains = false;
|
||||
var contains = false;
|
||||
if (lbl.labelForProperty().get() != null) {
|
||||
Node labeledNode = lbl.labelForProperty().get();
|
||||
var labeledNode = lbl.labelForProperty().get();
|
||||
contains |= labeledNode.toString().toLowerCase().contains(filter);
|
||||
if (labeledNode instanceof Control) {
|
||||
contains |= ofNullable(((Control) labeledNode).getTooltip()).map(Tooltip::getText).orElse("").toLowerCase().contains(filter);
|
||||
|
@ -66,7 +66,7 @@ class HighlightingSupport {
|
|||
}
|
||||
|
||||
static void removeHighlights(Category cat) {
|
||||
Node node = cat.getGuiOrElse(Label::new);
|
||||
var node = cat.getGuiOrElse(Label::new);
|
||||
removeHighlights(node);
|
||||
if(cat.hasSubCategories()) {
|
||||
for (Category sub : cat.getSubCategories()) {
|
||||
|
|
|
@ -72,17 +72,17 @@ public class Preferences {
|
|||
}
|
||||
|
||||
public Region getView(boolean withNavigation) {
|
||||
SearchBox search = new SearchBox(true);
|
||||
var search = new SearchBox(true);
|
||||
search.textProperty().addListener(this::filterTree);
|
||||
TreeItem<Category> categoryTreeItems = createCategoryTree(categories, new TreeItem<>(), null);
|
||||
categoryTree = new TreeView<>(categoryTreeItems);
|
||||
categoryTree.showRootProperty().set(false);
|
||||
VBox leftSide = new VBox(search, categoryTree);
|
||||
var leftSide = new VBox(search, categoryTree);
|
||||
VBox.setVgrow(categoryTree, Priority.ALWAYS);
|
||||
VBox.setMargin(search, new Insets(2));
|
||||
VBox.setMargin(categoryTree, new Insets(2));
|
||||
|
||||
BorderPane main = new BorderPane();
|
||||
var main = new BorderPane();
|
||||
if (withNavigation) {
|
||||
main.setLeft(leftSide);
|
||||
}
|
||||
|
@ -149,9 +149,9 @@ public class Preferences {
|
|||
}
|
||||
|
||||
private Node createPaneWithGroups(Category cat) throws Exception {
|
||||
VBox pane = new VBox();
|
||||
var pane = new VBox();
|
||||
for (Group grp : cat.getGroups()) {
|
||||
Label groupLabel = new Label(grp.getName());
|
||||
var groupLabel = new Label(grp.getName());
|
||||
groupLabel.getStyleClass().add("settings-group-label");
|
||||
VBox.setMargin(groupLabel, new Insets(20, 0, 10, 20));
|
||||
pane.getChildren().add(groupLabel);
|
||||
|
@ -163,13 +163,13 @@ public class Preferences {
|
|||
}
|
||||
|
||||
private Node createGrid(Setting[] settings) throws Exception {
|
||||
GridPane pane = new GridPane();
|
||||
var pane = new GridPane();
|
||||
pane.setHgap(2);
|
||||
pane.vgapProperty().bind(pane.hgapProperty());
|
||||
int row = 0;
|
||||
var row = 0;
|
||||
for (Setting setting : settings) {
|
||||
Node node = setting.getGui();
|
||||
Label label = new Label(setting.getName());
|
||||
var node = setting.getGui();
|
||||
var label = new Label(setting.getName());
|
||||
label.setMinHeight(34);
|
||||
label.labelForProperty().set(node);
|
||||
label.setTooltip(new Tooltip(setting.getName()));
|
||||
|
@ -226,7 +226,7 @@ public class Preferences {
|
|||
}
|
||||
|
||||
public Optional<Setting> getSetting(String key) {
|
||||
SettingSearchVisitor search = new SettingSearchVisitor(key);
|
||||
var search = new SettingSearchVisitor(key);
|
||||
traverse(search);
|
||||
return search.getResult();
|
||||
}
|
||||
|
|
|
@ -9,5 +9,5 @@ public interface PreferencesStorage {
|
|||
void save(Preferences preferences) throws IOException;
|
||||
void load(Preferences preferences);
|
||||
|
||||
Node createGui(Setting setting) throws Exception;
|
||||
Node createGui(Setting setting) throws NoSuchFieldException, IllegalAccessException;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package ctbrec.ui.settings.api;
|
|||
import static java.util.Optional.*;
|
||||
|
||||
import ctbrec.StringUtil;
|
||||
import ctbrec.ui.controls.Dialogs;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.scene.Node;
|
||||
|
@ -35,13 +36,13 @@ public class Setting {
|
|||
}
|
||||
|
||||
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;
|
||||
return setting;
|
||||
}
|
||||
|
||||
public static Setting of(String name, Node gui) {
|
||||
Setting setting = new Setting(name, gui);
|
||||
var setting = new Setting(name, gui);
|
||||
return setting;
|
||||
}
|
||||
|
||||
|
@ -79,12 +80,16 @@ public class Setting {
|
|||
return property;
|
||||
}
|
||||
|
||||
public Node getGui() throws Exception {
|
||||
public Node getGui() {
|
||||
if (gui == null) {
|
||||
gui = preferencesStorage.createGui(this);
|
||||
if (gui instanceof Control && StringUtil.isNotBlank(tooltip)) {
|
||||
Control control = (Control) gui;
|
||||
control.setTooltip(new Tooltip(tooltip));
|
||||
try {
|
||||
gui = preferencesStorage.createGui(this);
|
||||
if (gui instanceof Control && StringUtil.isNotBlank(tooltip)) {
|
||||
var control = (Control) gui;
|
||||
control.setTooltip(new Tooltip(tooltip));
|
||||
}
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
Dialogs.showError("Error", "Error creating settings GUI", e);
|
||||
}
|
||||
}
|
||||
return gui;
|
||||
|
|
|
@ -9,7 +9,7 @@ import ctbrec.Config;
|
|||
|
||||
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() {
|
||||
try {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package ctbrec.ui.sites.bonga;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Settings;
|
||||
import ctbrec.sites.bonga.BongaCams;
|
||||
import ctbrec.ui.DesktopIntegration;
|
||||
import ctbrec.ui.settings.SettingsTab;
|
||||
|
@ -26,14 +25,14 @@ public class BongaCamsConfigUI extends AbstractConfigUI {
|
|||
@Override
|
||||
public Parent createConfigPanel() {
|
||||
GridPane layout = SettingsTab.createGridLayout();
|
||||
Settings settings = Config.getInstance().getSettings();
|
||||
var settings = Config.getInstance().getSettings();
|
||||
|
||||
int row = 0;
|
||||
Label l = new Label("Active");
|
||||
var row = 0;
|
||||
var l = new Label("Active");
|
||||
layout.add(l, 0, row);
|
||||
CheckBox enabled = new CheckBox();
|
||||
var enabled = new CheckBox();
|
||||
enabled.setSelected(!settings.disabledSites.contains(bongaCams.getName()));
|
||||
enabled.setOnAction((e) -> {
|
||||
enabled.setOnAction(e -> {
|
||||
if(enabled.isSelected()) {
|
||||
settings.disabledSites.remove(bongaCams.getName());
|
||||
} else {
|
||||
|
@ -45,7 +44,7 @@ public class BongaCamsConfigUI extends AbstractConfigUI {
|
|||
layout.add(enabled, 1, 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.textProperty().addListener((ob, o, n) -> {
|
||||
if(!n.equals(Config.getInstance().getSettings().bongaUsername)) {
|
||||
|
@ -60,7 +59,7 @@ public class BongaCamsConfigUI extends AbstractConfigUI {
|
|||
layout.add(username, 1, row++);
|
||||
|
||||
layout.add(new Label("BongaCams Password"), 0, row);
|
||||
PasswordField password = new PasswordField();
|
||||
var password = new PasswordField();
|
||||
password.setText(settings.bongaPassword);
|
||||
password.textProperty().addListener((ob, o, n) -> {
|
||||
if(!n.equals(Config.getInstance().getSettings().bongaPassword)) {
|
||||
|
@ -75,7 +74,7 @@ public class BongaCamsConfigUI extends AbstractConfigUI {
|
|||
layout.add(password, 1, 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.textProperty().addListener((ob, o, n) -> {
|
||||
Config.getInstance().getSettings().bongacamsBaseUrl = baseUrl.getText();
|
||||
|
@ -86,9 +85,9 @@ public class BongaCamsConfigUI extends AbstractConfigUI {
|
|||
GridPane.setColumnSpan(baseUrl, 2);
|
||||
layout.add(baseUrl, 1, row++);
|
||||
|
||||
Button createAccount = new Button("Create new Account");
|
||||
createAccount.setOnAction((e) -> DesktopIntegration.open(bongaCams.getAffiliateLink()));
|
||||
layout.add(createAccount, 1, row++);
|
||||
var createAccount = new Button("Create new Account");
|
||||
createAccount.setOnAction(e -> DesktopIntegration.open(bongaCams.getAffiliateLink()));
|
||||
layout.add(createAccount, 1, row);
|
||||
GridPane.setColumnSpan(createAccount, 2);
|
||||
GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||
GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||
|
|
|
@ -7,7 +7,6 @@ import java.util.Collections;
|
|||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -32,11 +31,11 @@ public class BongaCamsElectronLoginDialog {
|
|||
this.cookieJar = cookieJar;
|
||||
browser = ExternalBrowser.getInstance();
|
||||
try {
|
||||
JSONObject config = new JSONObject();
|
||||
var config = new JSONObject();
|
||||
config.put("url", URL);
|
||||
config.put("w", 640);
|
||||
config.put("h", 480);
|
||||
JSONObject msg = new JSONObject();
|
||||
var msg = new JSONObject();
|
||||
msg.put("config", config);
|
||||
browser.run(msg, msgHandler);
|
||||
} catch (InterruptedException e) {
|
||||
|
@ -51,9 +50,9 @@ public class BongaCamsElectronLoginDialog {
|
|||
if(!line.startsWith("{")) {
|
||||
LOG.error("Didn't received a JSON object {}", line);
|
||||
} else {
|
||||
JSONObject json = new JSONObject(line);
|
||||
var json = new JSONObject(line);
|
||||
if(json.has("url")) {
|
||||
String url = json.getString("url");
|
||||
var url = json.getString("url");
|
||||
if(url.endsWith("/login")) {
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
|
@ -66,7 +65,7 @@ public class BongaCamsElectronLoginDialog {
|
|||
password = password.replace("'", "\\'");
|
||||
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~=\"header_bar\"]').css('display','none')",
|
||||
"$('footer').css('display','none');",
|
||||
|
@ -76,15 +75,18 @@ public class BongaCamsElectronLoginDialog {
|
|||
for (String js : simplify) {
|
||||
browser.executeJavaScript(js);
|
||||
}
|
||||
} catch(InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
LOG.warn("Couldn't auto fill username and password for BongaCams", e);
|
||||
} catch(Exception e) {
|
||||
LOG.warn("Couldn't auto fill username and password for BongaCams", e);
|
||||
}
|
||||
}
|
||||
|
||||
if(json.has("cookies")) {
|
||||
JSONArray cookiesFromBrowser = json.getJSONArray("cookies");
|
||||
for (int i = 0; i < cookiesFromBrowser.length(); i++) {
|
||||
JSONObject cookie = cookiesFromBrowser.getJSONObject(i);
|
||||
var cookiesFromBrowser = json.getJSONArray("cookies");
|
||||
for (var i = 0; i < cookiesFromBrowser.length(); i++) {
|
||||
var cookie = cookiesFromBrowser.getJSONObject(i);
|
||||
if(cookie.getString("domain").contains(DOMAIN)) {
|
||||
Builder b = new Cookie.Builder()
|
||||
.path(cookie.getString("path"))
|
||||
|
|
|
@ -11,7 +11,7 @@ import ctbrec.ui.tabs.ThumbOverviewTab;
|
|||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Tab;
|
||||
|
||||
public class BongaCamsTabProvider extends TabProvider {
|
||||
public class BongaCamsTabProvider implements TabProvider {
|
||||
|
||||
private BongaCams bongaCams;
|
||||
private Recorder recorder;
|
||||
|
@ -28,7 +28,7 @@ public class BongaCamsTabProvider extends TabProvider {
|
|||
|
||||
// female
|
||||
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));
|
||||
|
||||
// male
|
||||
|
@ -67,7 +67,7 @@ public class BongaCamsTabProvider extends TabProvider {
|
|||
}
|
||||
|
||||
private Tab createTab(String title, PaginatedScheduledService updateService) {
|
||||
ThumbOverviewTab tab = new ThumbOverviewTab(title, updateService, bongaCams);
|
||||
var tab = new ThumbOverviewTab(title, updateService, bongaCams);
|
||||
tab.setRecorder(recorder);
|
||||
return tab;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ import ctbrec.sites.bonga.BongaCamsModel;
|
|||
import ctbrec.ui.tabs.PaginatedScheduledService;
|
||||
import javafx.concurrent.Task;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class BongaCamsUpdateService extends PaginatedScheduledService {
|
||||
|
||||
|
@ -38,48 +37,56 @@ public class BongaCamsUpdateService extends PaginatedScheduledService {
|
|||
return new Task<List<Model>>() {
|
||||
@Override
|
||||
public List<Model> call() throws IOException {
|
||||
String pageUrl = url + ((page-1) * 36);
|
||||
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);
|
||||
}
|
||||
return loadModelList();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package ctbrec.ui.sites.cam4;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Settings;
|
||||
import ctbrec.sites.cam4.Cam4;
|
||||
import ctbrec.ui.DesktopIntegration;
|
||||
import ctbrec.ui.settings.SettingsTab;
|
||||
|
@ -25,15 +24,15 @@ public class Cam4ConfigUI extends AbstractConfigUI {
|
|||
|
||||
@Override
|
||||
public Parent createConfigPanel() {
|
||||
GridPane layout = SettingsTab.createGridLayout();
|
||||
Settings settings = Config.getInstance().getSettings();
|
||||
var layout = SettingsTab.createGridLayout();
|
||||
var settings = Config.getInstance().getSettings();
|
||||
|
||||
int row = 0;
|
||||
Label l = new Label("Active");
|
||||
var row = 0;
|
||||
var l = new Label("Active");
|
||||
layout.add(l, 0, row);
|
||||
CheckBox enabled = new CheckBox();
|
||||
var enabled = new CheckBox();
|
||||
enabled.setSelected(!settings.disabledSites.contains(cam4.getName()));
|
||||
enabled.setOnAction((e) -> {
|
||||
enabled.setOnAction(e -> {
|
||||
if(enabled.isSelected()) {
|
||||
settings.disabledSites.remove(cam4.getName());
|
||||
} else {
|
||||
|
@ -45,7 +44,7 @@ public class Cam4ConfigUI extends AbstractConfigUI {
|
|||
layout.add(enabled, 1, 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) -> {
|
||||
if(!n.equals(Config.getInstance().getSettings().cam4Username)) {
|
||||
Config.getInstance().getSettings().cam4Username = username.getText();
|
||||
|
@ -59,7 +58,7 @@ public class Cam4ConfigUI extends AbstractConfigUI {
|
|||
layout.add(username, 1, row++);
|
||||
|
||||
layout.add(new Label("Cam4 Password"), 0, row);
|
||||
PasswordField password = new PasswordField();
|
||||
var password = new PasswordField();
|
||||
password.setText(Config.getInstance().getSettings().cam4Password);
|
||||
password.textProperty().addListener((ob, o, n) -> {
|
||||
if(!n.equals(Config.getInstance().getSettings().cam4Password)) {
|
||||
|
@ -73,9 +72,9 @@ public class Cam4ConfigUI extends AbstractConfigUI {
|
|||
GridPane.setColumnSpan(password, 2);
|
||||
layout.add(password, 1, row++);
|
||||
|
||||
Button createAccount = new Button("Create new Account");
|
||||
createAccount.setOnAction((e) -> DesktopIntegration.open(Cam4.AFFILIATE_LINK));
|
||||
layout.add(createAccount, 1, row++);
|
||||
var createAccount = new Button("Create new Account");
|
||||
createAccount.setOnAction(e -> DesktopIntegration.open(Cam4.AFFILIATE_LINK));
|
||||
layout.add(createAccount, 1, row);
|
||||
GridPane.setColumnSpan(createAccount, 2);
|
||||
GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||
GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||
|
|
|
@ -7,7 +7,6 @@ import java.util.Collections;
|
|||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -32,11 +31,11 @@ public class Cam4ElectronLoginDialog {
|
|||
this.cookieJar = cookieJar;
|
||||
browser = ExternalBrowser.getInstance();
|
||||
try {
|
||||
JSONObject config = new JSONObject();
|
||||
var config = new JSONObject();
|
||||
config.put("url", URL);
|
||||
config.put("w", 480);
|
||||
config.put("h", 640);
|
||||
JSONObject msg = new JSONObject();
|
||||
var msg = new JSONObject();
|
||||
msg.put("config", config);
|
||||
browser.run(msg, msgHandler);
|
||||
} catch (InterruptedException e) {
|
||||
|
@ -51,9 +50,9 @@ public class Cam4ElectronLoginDialog {
|
|||
if(!line.startsWith("{")) {
|
||||
LOG.error("Didn't received a JSON object {}", line);
|
||||
} else {
|
||||
JSONObject json = new JSONObject(line);
|
||||
if(json.has("url")) {
|
||||
String url = json.getString("url");
|
||||
var json = new JSONObject(line);
|
||||
if (json.has("url")) {
|
||||
var url = json.getString("url");
|
||||
|
||||
if(url.endsWith("/login")) {
|
||||
try {
|
||||
|
@ -76,16 +75,16 @@ public class Cam4ElectronLoginDialog {
|
|||
}
|
||||
|
||||
if(json.has("cookies")) {
|
||||
JSONArray cookiesFromBrowser = json.getJSONArray("cookies");
|
||||
var cookiesFromBrowser = json.getJSONArray("cookies");
|
||||
try {
|
||||
for (int i = 0; i < cookiesFromBrowser.length(); i++) {
|
||||
JSONObject cookie = cookiesFromBrowser.getJSONObject(i);
|
||||
for (var i = 0; i < cookiesFromBrowser.length(); i++) {
|
||||
var cookie = cookiesFromBrowser.getJSONObject(i);
|
||||
if(cookie.getString("domain").contains("cam4")) {
|
||||
String domain = cookie.getString("domain");
|
||||
var domain = cookie.getString("domain");
|
||||
if(domain.startsWith(".")) {
|
||||
domain = domain.substring(1);
|
||||
}
|
||||
Cookie c = createCookie(domain, cookie);
|
||||
var c = createCookie(domain, cookie);
|
||||
cookieJar.saveFromResponse(HttpUrl.parse(url), Collections.singletonList(c));
|
||||
c = createCookie("cam4.com", cookie);
|
||||
cookieJar.saveFromResponse(HttpUrl.parse(Cam4.BASE_URI), Collections.singletonList(c));
|
||||
|
|
|
@ -29,17 +29,17 @@ public class Cam4FollowedTab extends ThumbOverviewTab implements FollowedTab {
|
|||
}
|
||||
|
||||
private void addOnlineOfflineSelector() {
|
||||
ToggleGroup group = new ToggleGroup();
|
||||
RadioButton online = new RadioButton("online");
|
||||
var group = new ToggleGroup();
|
||||
var online = new RadioButton("online");
|
||||
online.setToggleGroup(group);
|
||||
RadioButton offline = new RadioButton("offline");
|
||||
var offline = new RadioButton("offline");
|
||||
offline.setToggleGroup(group);
|
||||
pagination.getChildren().add(online);
|
||||
pagination.getChildren().add(offline);
|
||||
HBox.setMargin(online, new Insets(5,5,5,40));
|
||||
HBox.setMargin(offline, new Insets(5,5,5,5));
|
||||
online.setSelected(true);
|
||||
group.selectedToggleProperty().addListener((e) -> {
|
||||
group.selectedToggleProperty().addListener(e -> {
|
||||
((Cam4FollowedUpdateService)updateService).setShowOnline(online.isSelected());
|
||||
queue.clear();
|
||||
updateService.restart();
|
||||
|
@ -66,10 +66,8 @@ public class Cam4FollowedTab extends ThumbOverviewTab implements FollowedTab {
|
|||
|
||||
public void setScene(Scene scene) {
|
||||
scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
||||
if(this.isSelected()) {
|
||||
if(event.getCode() == KeyCode.DELETE) {
|
||||
follow(selectedThumbCells, false);
|
||||
}
|
||||
if (this.isSelected() && event.getCode() == KeyCode.DELETE) {
|
||||
follow(selectedThumbCells, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import java.util.List;
|
|||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import ctbrec.Model;
|
||||
|
@ -17,7 +16,6 @@ import ctbrec.ui.SiteUiFactory;
|
|||
import ctbrec.ui.tabs.PaginatedScheduledService;
|
||||
import javafx.concurrent.Task;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class Cam4FollowedUpdateService extends PaginatedScheduledService {
|
||||
|
||||
|
@ -27,7 +25,7 @@ public class Cam4FollowedUpdateService extends PaginatedScheduledService {
|
|||
public Cam4FollowedUpdateService(Cam4 site) {
|
||||
this.site = site;
|
||||
ExecutorService executor = Executors.newSingleThreadExecutor(r -> {
|
||||
Thread t = new Thread(r);
|
||||
var t = new Thread(r);
|
||||
t.setDaemon(true);
|
||||
t.setName("ThumbOverviewTab UpdateService");
|
||||
return t;
|
||||
|
@ -40,37 +38,45 @@ public class Cam4FollowedUpdateService extends PaginatedScheduledService {
|
|||
return new Task<List<Model>>() {
|
||||
@Override
|
||||
public List<Model> call() throws IOException {
|
||||
// login first
|
||||
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());
|
||||
}
|
||||
}
|
||||
return loadModelList();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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) {
|
||||
this.showOnline = online;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import ctbrec.ui.tabs.ThumbOverviewTab;
|
|||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Tab;
|
||||
|
||||
public class Cam4TabProvider extends TabProvider {
|
||||
public class Cam4TabProvider implements TabProvider {
|
||||
|
||||
private Cam4 cam4;
|
||||
private Recorder recorder;
|
||||
|
@ -44,8 +44,8 @@ public class Cam4TabProvider extends TabProvider {
|
|||
}
|
||||
|
||||
private Tab createTab(String name, String url) {
|
||||
Cam4UpdateService updateService = new Cam4UpdateService(url, false, cam4);
|
||||
ThumbOverviewTab tab = new ThumbOverviewTab(name, updateService, cam4);
|
||||
var updateService = new Cam4UpdateService(url, false, cam4);
|
||||
var tab = new ThumbOverviewTab(name, updateService, cam4);
|
||||
tab.setRecorder(recorder);
|
||||
return tab;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import java.util.concurrent.Executors;
|
|||
|
||||
import org.json.JSONObject;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -28,7 +27,6 @@ import ctbrec.ui.SiteUiFactory;
|
|||
import ctbrec.ui.tabs.PaginatedScheduledService;
|
||||
import javafx.concurrent.Task;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class Cam4UpdateService extends PaginatedScheduledService {
|
||||
|
||||
|
@ -43,7 +41,7 @@ public class Cam4UpdateService extends PaginatedScheduledService {
|
|||
this.loginRequired = loginRequired;
|
||||
|
||||
ExecutorService executor = Executors.newSingleThreadExecutor(r -> {
|
||||
Thread t = new Thread(r);
|
||||
var t = new Thread(r);
|
||||
t.setDaemon(true);
|
||||
t.setName("ThumbOverviewTab UpdateService");
|
||||
return t;
|
||||
|
@ -64,35 +62,14 @@ public class Cam4UpdateService extends PaginatedScheduledService {
|
|||
if (loginRequired) {
|
||||
SiteUiFactory.getUi(site).login();
|
||||
}
|
||||
Request request = new Request.Builder()
|
||||
var request = new Request.Builder()
|
||||
.url(pageUrl)
|
||||
.header(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage())
|
||||
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
||||
.build();
|
||||
try (Response response = site.getHttpClient().execute(request)) {
|
||||
try (var response = site.getHttpClient().execute(request)) {
|
||||
if (response.isSuccessful()) {
|
||||
JSONObject json = new JSONObject(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;
|
||||
return parseModels(response.body().string());
|
||||
} else {
|
||||
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) {
|
||||
this.url = url;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package ctbrec.ui.sites.camsoda;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Settings;
|
||||
import ctbrec.sites.camsoda.Camsoda;
|
||||
import ctbrec.ui.DesktopIntegration;
|
||||
import ctbrec.ui.settings.SettingsTab;
|
||||
|
@ -25,15 +24,15 @@ public class CamsodaConfigUI extends AbstractConfigUI {
|
|||
|
||||
@Override
|
||||
public Parent createConfigPanel() {
|
||||
GridPane layout = SettingsTab.createGridLayout();
|
||||
Settings settings = Config.getInstance().getSettings();
|
||||
var layout = SettingsTab.createGridLayout();
|
||||
var settings = Config.getInstance().getSettings();
|
||||
|
||||
int row = 0;
|
||||
Label l = new Label("Active");
|
||||
var row = 0;
|
||||
var l = new Label("Active");
|
||||
layout.add(l, 0, row);
|
||||
CheckBox enabled = new CheckBox();
|
||||
var enabled = new CheckBox();
|
||||
enabled.setSelected(!settings.disabledSites.contains(camsoda.getName()));
|
||||
enabled.setOnAction((e) -> {
|
||||
enabled.setOnAction(e -> {
|
||||
if(enabled.isSelected()) {
|
||||
settings.disabledSites.remove(camsoda.getName());
|
||||
} else {
|
||||
|
@ -45,7 +44,7 @@ public class CamsodaConfigUI extends AbstractConfigUI {
|
|||
layout.add(enabled, 1, 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) -> {
|
||||
if(!n.equals(Config.getInstance().getSettings().camsodaUsername)) {
|
||||
Config.getInstance().getSettings().camsodaUsername = username.getText();
|
||||
|
@ -59,7 +58,7 @@ public class CamsodaConfigUI extends AbstractConfigUI {
|
|||
layout.add(username, 1, row++);
|
||||
|
||||
layout.add(new Label("CamSoda Password"), 0, row);
|
||||
PasswordField password = new PasswordField();
|
||||
var password = new PasswordField();
|
||||
password.setText(Config.getInstance().getSettings().camsodaPassword);
|
||||
password.textProperty().addListener((ob, o, n) -> {
|
||||
if(!n.equals(Config.getInstance().getSettings().camsodaPassword)) {
|
||||
|
@ -73,9 +72,9 @@ public class CamsodaConfigUI extends AbstractConfigUI {
|
|||
GridPane.setColumnSpan(password, 2);
|
||||
layout.add(password, 1, row++);
|
||||
|
||||
Button createAccount = new Button("Create new Account");
|
||||
createAccount.setOnAction((e) -> DesktopIntegration.open(camsoda.getAffiliateLink()));
|
||||
layout.add(createAccount, 1, row++);
|
||||
var createAccount = new Button("Create new Account");
|
||||
createAccount.setOnAction(e -> DesktopIntegration.open(camsoda.getAffiliateLink()));
|
||||
layout.add(createAccount, 1, row);
|
||||
GridPane.setColumnSpan(createAccount, 2);
|
||||
GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||
GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||
|
|
|
@ -34,10 +34,10 @@ public class CamsodaFollowedTab extends ThumbOverviewTab implements FollowedTab
|
|||
}
|
||||
|
||||
private void addOnlineOfflineSelector() {
|
||||
ToggleGroup group = new ToggleGroup();
|
||||
RadioButton online = new RadioButton("online");
|
||||
var group = new ToggleGroup();
|
||||
var online = new RadioButton("online");
|
||||
online.setToggleGroup(group);
|
||||
RadioButton offline = new RadioButton("offline");
|
||||
var offline = new RadioButton("offline");
|
||||
offline.setToggleGroup(group);
|
||||
pagination.getChildren().add(online);
|
||||
pagination.getChildren().add(offline);
|
||||
|
@ -59,7 +59,7 @@ public class CamsodaFollowedTab extends ThumbOverviewTab implements FollowedTab
|
|||
|
||||
@Override
|
||||
protected void onFail(WorkerStateEvent event) {
|
||||
String msg = "";
|
||||
var msg = "";
|
||||
if (event.getSource().getException() != null) {
|
||||
msg = ": " + event.getSource().getException().getMessage();
|
||||
}
|
||||
|
@ -75,10 +75,8 @@ public class CamsodaFollowedTab extends ThumbOverviewTab implements FollowedTab
|
|||
|
||||
public void setScene(Scene scene) {
|
||||
scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
||||
if (this.isSelected()) {
|
||||
if (event.getCode() == KeyCode.DELETE) {
|
||||
follow(selectedThumbCells, false);
|
||||
}
|
||||
if (this.isSelected() && event.getCode() == KeyCode.DELETE) {
|
||||
follow(selectedThumbCells, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -8,13 +8,12 @@ import java.time.ZoneId;
|
|||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.FormatStyle;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -69,7 +68,7 @@ public class CamsodaShowsTab extends Tab implements TabSelectionListener {
|
|||
showList.setPadding(new Insets(5));
|
||||
showList.setHgap(5);
|
||||
showList.setVgap(5);
|
||||
ProgressIndicator progressIndicator = new ProgressIndicator();
|
||||
var progressIndicator = new ProgressIndicator();
|
||||
progressIndicator.setPrefSize(100, 100);
|
||||
setContent(progressIndicator);
|
||||
setClosable(false);
|
||||
|
@ -81,41 +80,7 @@ public class CamsodaShowsTab extends Tab implements TabSelectionListener {
|
|||
Task<List<ShowBox>> task = new Task<List<ShowBox>>() {
|
||||
@Override
|
||||
protected List<ShowBox> call() throws Exception {
|
||||
String url = camsoda.getBaseUrl() + "/api/v1/user/model_shows";
|
||||
Request req = new Request.Builder().url(url).build();
|
||||
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());
|
||||
return loadShows();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -125,11 +90,14 @@ public class CamsodaShowsTab extends Tab implements TabSelectionListener {
|
|||
try {
|
||||
List<ShowBox> boxes = get();
|
||||
showList.getChildren().clear();
|
||||
int index = 0;
|
||||
var index = 0;
|
||||
for (ShowBox showBox : boxes) {
|
||||
showList.add(showBox, index % 2, index++ / 2);
|
||||
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) {
|
||||
LOG.error("Couldn't load upcoming camsoda shows", e);
|
||||
}
|
||||
|
@ -140,6 +108,44 @@ public class CamsodaShowsTab extends Tab implements TabSelectionListener {
|
|||
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
|
||||
public void deselected() {
|
||||
// nothing to do
|
||||
|
@ -165,31 +171,31 @@ public class CamsodaShowsTab extends Tab implements TabSelectionListener {
|
|||
setPrefHeight(268);
|
||||
setContent(root);
|
||||
|
||||
ImageView thumb = new ImageView();
|
||||
var thumb = new ImageView();
|
||||
thumb.setPreserveRatio(true);
|
||||
thumb.setFitHeight(thumbSize);
|
||||
loadImage(model, thumb);
|
||||
root.setLeft(new ProgressIndicator());
|
||||
BorderPane.setMargin(thumb, new Insets(10, 30, 10, 10));
|
||||
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.MEDIUM);
|
||||
GridPane grid = new GridPane();
|
||||
var formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.MEDIUM);
|
||||
var grid = new GridPane();
|
||||
|
||||
grid.add(createLabel("Start", true), 0, 0);
|
||||
grid.add(createLabel(formatter.format(startTime), false), 1, 0);
|
||||
grid.add(createLabel("End", true), 0, 1);
|
||||
grid.add(createLabel(formatter.format(endTime), false), 1, 1);
|
||||
Button record = new Button("Record Model");
|
||||
record.setTooltip(new Tooltip(record.getText()));
|
||||
record.setOnAction(evt -> record(model));
|
||||
grid.add(record, 1, 2);
|
||||
GridPane.setMargin(record, new Insets(10));
|
||||
Button follow = new Button("Follow");
|
||||
var recordButton = new Button("Record Model");
|
||||
recordButton.setTooltip(new Tooltip(recordButton.getText()));
|
||||
recordButton.setOnAction(evt -> recordModel(model));
|
||||
grid.add(recordButton, 1, 2);
|
||||
GridPane.setMargin(recordButton, new Insets(10));
|
||||
var follow = new Button("Follow");
|
||||
follow.setTooltip(new Tooltip(follow.getText()));
|
||||
follow.setOnAction(evt -> follow(model));
|
||||
grid.add(follow, 1, 3);
|
||||
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.setOnAction(evt -> DesktopIntegration.open(model.getUrl()));
|
||||
grid.add(openInBrowser, 1, 4);
|
||||
|
@ -197,7 +203,7 @@ public class CamsodaShowsTab extends Tab implements TabSelectionListener {
|
|||
root.setCenter(grid);
|
||||
loadImage(model, thumb);
|
||||
|
||||
record.minWidthProperty().bind(openInBrowser.widthProperty());
|
||||
recordButton.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);
|
||||
GlobalThreadPool.submit(() -> {
|
||||
try {
|
||||
|
@ -233,47 +239,56 @@ public class CamsodaShowsTab extends Tab implements TabSelectionListener {
|
|||
GlobalThreadPool.submit(() -> {
|
||||
try {
|
||||
String url = camsoda.getBaseUrl() + "/api/v1/user/" + model.getName();
|
||||
Request detailRequest = new Request.Builder().url(url).build();
|
||||
Response resp = camsoda.getHttpClient().execute(detailRequest);
|
||||
if (resp.isSuccessful()) {
|
||||
JSONObject json = new JSONObject(resp.body().string());
|
||||
if (json.optBoolean("status") && json.has("user")) {
|
||||
JSONObject user = json.getJSONObject("user");
|
||||
if (user.has("settings")) {
|
||||
JSONObject settings = user.getJSONObject("settings");
|
||||
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);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
var detailRequest = new Request.Builder().url(url).build();
|
||||
try (Response resp = camsoda.getHttpClient().execute(detailRequest)) {
|
||||
if (resp.isSuccessful()) {
|
||||
parseImageUrl(resp.body().string()).ifPresent(imageUrl -> updateImageView(thumb, imageUrl));
|
||||
}
|
||||
}
|
||||
resp.close();
|
||||
} catch (Exception 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) {
|
||||
Label label = new Label(string);
|
||||
var label = new Label(string);
|
||||
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));
|
||||
return label;
|
||||
}
|
||||
|
|
|
@ -34,58 +34,4 @@ public class CamsodaSiteUi extends AbstractSiteUi {
|
|||
boolean automaticLogin = camsoda.login();
|
||||
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);
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ import ctbrec.ui.tabs.ThumbOverviewTab;
|
|||
import javafx.scene.Scene;
|
||||
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 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("Couples", API_URL, m -> Objects.equals("c", 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.setScene(scene);
|
||||
tabs.add(followedTab);
|
||||
|
@ -51,8 +50,8 @@ public class CamsodaTabProvider extends TabProvider {
|
|||
}
|
||||
|
||||
private Tab createTab(String title, String url, Predicate<CamsodaModel> filter) {
|
||||
CamsodaUpdateService updateService = new CamsodaUpdateService(url, false, camsoda, filter);
|
||||
ThumbOverviewTab tab = new ThumbOverviewTab(title, updateService, camsoda);
|
||||
var updateService = new CamsodaUpdateService(url, false, camsoda, filter);
|
||||
var tab = new ThumbOverviewTab(title, updateService, camsoda);
|
||||
tab.setRecorder(recorder);
|
||||
return tab;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ import ctbrec.ui.SiteUiFactory;
|
|||
import ctbrec.ui.tabs.PaginatedScheduledService;
|
||||
import javafx.concurrent.Task;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class CamsodaUpdateService extends PaginatedScheduledService {
|
||||
|
||||
|
@ -53,7 +52,7 @@ public class CamsodaUpdateService extends PaginatedScheduledService {
|
|||
return loadOnlineModels().stream()
|
||||
.sorted((m1,m2) -> (int)(m2.getSortOrder() - m1.getSortOrder()))
|
||||
.filter(filter)
|
||||
.skip( (page-1) * modelsPerPage)
|
||||
.skip( (page-1) * (long)modelsPerPage)
|
||||
.limit(modelsPerPage)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
@ -61,71 +60,17 @@ public class CamsodaUpdateService extends PaginatedScheduledService {
|
|||
}
|
||||
|
||||
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();
|
||||
} else {
|
||||
LOG.debug("Fetching page {}", url);
|
||||
if(loginRequired) {
|
||||
if (loginRequired) {
|
||||
SiteUiFactory.getUi(camsoda).login();
|
||||
}
|
||||
Request request = new Request.Builder().url(url).build();
|
||||
try (Response response = camsoda.getHttpClient().execute(request)) {
|
||||
var request = new Request.Builder().url(url).build();
|
||||
try (var response = camsoda.getHttpClient().execute(request)) {
|
||||
if (response.isSuccessful()) {
|
||||
String body = 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;
|
||||
return parseModels(response.body().string());
|
||||
} else {
|
||||
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) {
|
||||
for (int i = 0; i < template.length(); i++) {
|
||||
String s = template.getString(i);
|
||||
if(Objects.equals(s, string)) {
|
||||
for (var i = 0; i < template.length(); i++) {
|
||||
var s = template.getString(i);
|
||||
if (Objects.equals(s, string)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package ctbrec.ui.sites.chaturbate;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Settings;
|
||||
import ctbrec.sites.chaturbate.Chaturbate;
|
||||
import ctbrec.ui.DesktopIntegration;
|
||||
import ctbrec.ui.settings.SettingsTab;
|
||||
|
@ -25,15 +24,15 @@ public class ChaturbateConfigUi extends AbstractConfigUI {
|
|||
|
||||
@Override
|
||||
public Parent createConfigPanel() {
|
||||
Settings settings = Config.getInstance().getSettings();
|
||||
var settings = Config.getInstance().getSettings();
|
||||
GridPane layout = SettingsTab.createGridLayout();
|
||||
|
||||
int row = 0;
|
||||
Label l = new Label("Active");
|
||||
var row = 0;
|
||||
var l = new Label("Active");
|
||||
layout.add(l, 0, row);
|
||||
CheckBox enabled = new CheckBox();
|
||||
var enabled = new CheckBox();
|
||||
enabled.setSelected(!settings.disabledSites.contains(chaturbate.getName()));
|
||||
enabled.setOnAction((e) -> {
|
||||
enabled.setOnAction(e -> {
|
||||
if(enabled.isSelected()) {
|
||||
settings.disabledSites.remove(chaturbate.getName());
|
||||
} else {
|
||||
|
@ -45,7 +44,7 @@ public class ChaturbateConfigUi extends AbstractConfigUI {
|
|||
layout.add(enabled, 1, 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) -> {
|
||||
if(!n.equals(Config.getInstance().getSettings().chaturbateUsername)) {
|
||||
Config.getInstance().getSettings().chaturbateUsername = n;
|
||||
|
@ -59,7 +58,7 @@ public class ChaturbateConfigUi extends AbstractConfigUI {
|
|||
layout.add(username, 1, row++);
|
||||
|
||||
layout.add(new Label("Chaturbate Password"), 0, row);
|
||||
PasswordField password = new PasswordField();
|
||||
var password = new PasswordField();
|
||||
password.setText(Config.getInstance().getSettings().chaturbatePassword);
|
||||
password.textProperty().addListener((ob, o, n) -> {
|
||||
if(!n.equals(Config.getInstance().getSettings().chaturbatePassword)) {
|
||||
|
@ -74,7 +73,7 @@ public class ChaturbateConfigUi extends AbstractConfigUI {
|
|||
layout.add(password, 1, 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.textProperty().addListener((ob, o, n) -> {
|
||||
Config.getInstance().getSettings().chaturbateBaseUrl = baseUrl.getText();
|
||||
|
@ -85,9 +84,9 @@ public class ChaturbateConfigUi extends AbstractConfigUI {
|
|||
GridPane.setColumnSpan(baseUrl, 2);
|
||||
layout.add(baseUrl, 1, row++);
|
||||
|
||||
Button createAccount = new Button("Create new Account");
|
||||
createAccount.setOnAction((e) -> DesktopIntegration.open(Chaturbate.REGISTRATION_LINK));
|
||||
layout.add(createAccount, 1, row++);
|
||||
var createAccount = new Button("Create new Account");
|
||||
createAccount.setOnAction(e -> DesktopIntegration.open(Chaturbate.REGISTRATION_LINK));
|
||||
layout.add(createAccount, 1, row);
|
||||
GridPane.setColumnSpan(createAccount, 2);
|
||||
GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||
GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||
|
|
|
@ -34,17 +34,17 @@ public class ChaturbateFollowedTab extends ThumbOverviewTab implements FollowedT
|
|||
}
|
||||
|
||||
private void addOnlineOfflineSelector() {
|
||||
ToggleGroup group = new ToggleGroup();
|
||||
RadioButton online = new RadioButton("online");
|
||||
var group = new ToggleGroup();
|
||||
var online = new RadioButton("online");
|
||||
online.setToggleGroup(group);
|
||||
RadioButton offline = new RadioButton("offline");
|
||||
var offline = new RadioButton("offline");
|
||||
offline.setToggleGroup(group);
|
||||
pagination.getChildren().add(online);
|
||||
pagination.getChildren().add(offline);
|
||||
HBox.setMargin(online, new Insets(5,5,5,40));
|
||||
HBox.setMargin(offline, new Insets(5,5,5,5));
|
||||
online.setSelected(true);
|
||||
group.selectedToggleProperty().addListener((e) -> {
|
||||
group.selectedToggleProperty().addListener(e -> {
|
||||
if(online.isSelected()) {
|
||||
((ChaturbateUpdateService)updateService).setUrl(onlineUrl);
|
||||
} else {
|
||||
|
@ -75,10 +75,8 @@ public class ChaturbateFollowedTab extends ThumbOverviewTab implements FollowedT
|
|||
|
||||
public void setScene(Scene scene) {
|
||||
scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
||||
if(this.isSelected()) {
|
||||
if(event.getCode() == KeyCode.DELETE) {
|
||||
follow(selectedThumbCells, false);
|
||||
}
|
||||
if (this.isSelected() && event.getCode() == KeyCode.DELETE) {
|
||||
follow(selectedThumbCells, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import ctbrec.ui.tabs.ThumbOverviewTab;
|
|||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Tab;
|
||||
|
||||
public class ChaturbateTabProvider extends TabProvider {
|
||||
public class ChaturbateTabProvider implements TabProvider {
|
||||
|
||||
private Chaturbate chaturbate;
|
||||
private Recorder recorder;
|
||||
|
@ -44,8 +44,8 @@ public class ChaturbateTabProvider extends TabProvider {
|
|||
}
|
||||
|
||||
private Tab createTab(String title, String url) {
|
||||
ChaturbateUpdateService updateService = new ChaturbateUpdateService(url, false, chaturbate);
|
||||
ThumbOverviewTab tab = new ThumbOverviewTab(title, updateService, chaturbate);
|
||||
var updateService = new ChaturbateUpdateService(url, false, chaturbate);
|
||||
var tab = new ThumbOverviewTab(title, updateService, chaturbate);
|
||||
tab.setRecorder(recorder);
|
||||
tab.setImageAspectRatio(9.0 / 16.0);
|
||||
return tab;
|
||||
|
|
|
@ -16,7 +16,6 @@ import ctbrec.ui.SiteUiFactory;
|
|||
import ctbrec.ui.tabs.PaginatedScheduledService;
|
||||
import javafx.concurrent.Task;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class ChaturbateUpdateService extends PaginatedScheduledService {
|
||||
|
||||
|
@ -31,7 +30,7 @@ public class ChaturbateUpdateService extends PaginatedScheduledService {
|
|||
this.chaturbate = chaturbate;
|
||||
|
||||
ExecutorService executor = Executors.newSingleThreadExecutor(r -> {
|
||||
Thread t = new Thread(r);
|
||||
var t = new Thread(r);
|
||||
t.setDaemon(true);
|
||||
t.setName("ThumbOverviewTab UpdateService");
|
||||
return t;
|
||||
|
@ -44,7 +43,7 @@ public class ChaturbateUpdateService extends PaginatedScheduledService {
|
|||
return new Task<List<Model>>() {
|
||||
@Override
|
||||
public List<Model> call() throws IOException {
|
||||
if(loginRequired && !chaturbate.credentialsAvailable()) {
|
||||
if (loginRequired && !chaturbate.credentialsAvailable()) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
String pageUrl = ChaturbateUpdateService.this.url + "?page="+page+"&keywords=&_=" + System.currentTimeMillis();
|
||||
|
@ -52,16 +51,15 @@ public class ChaturbateUpdateService extends PaginatedScheduledService {
|
|||
if(loginRequired) {
|
||||
SiteUiFactory.getUi(chaturbate).login();
|
||||
}
|
||||
Request request = new Request.Builder().url(pageUrl).build();
|
||||
Response response = chaturbate.getHttpClient().execute(request);
|
||||
if (response.isSuccessful()) {
|
||||
List<Model> models = ChaturbateModelParser.parseModels(chaturbate, response.body().string());
|
||||
response.close();
|
||||
return models;
|
||||
} else {
|
||||
int code = response.code();
|
||||
response.close();
|
||||
throw new IOException("HTTP status " + code);
|
||||
var request = new Request.Builder().url(pageUrl).build();
|
||||
try (var response = chaturbate.getHttpClient().execute(request)) {
|
||||
if (response.isSuccessful()) {
|
||||
List<Model> models = ChaturbateModelParser.parseModels(chaturbate, response.body().string());
|
||||
return models;
|
||||
} else {
|
||||
int code = response.code();
|
||||
throw new IOException("HTTP status " + code);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,25 +14,19 @@ public class Fc2FollowedTab extends ThumbOverviewTab implements FollowedTab {
|
|||
super("Followed", new Fc2FollowedUpdateService(fc2live), fc2live);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createGui() {
|
||||
super.createGui();
|
||||
//addOnlineOfflineSelector();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void addOnlineOfflineSelector() {
|
||||
ToggleGroup group = new ToggleGroup();
|
||||
RadioButton online = new RadioButton("online");
|
||||
var group = new ToggleGroup();
|
||||
var online = new RadioButton("online");
|
||||
online.setToggleGroup(group);
|
||||
RadioButton offline = new RadioButton("offline");
|
||||
var offline = new RadioButton("offline");
|
||||
offline.setToggleGroup(group);
|
||||
pagination.getChildren().add(online);
|
||||
pagination.getChildren().add(offline);
|
||||
HBox.setMargin(online, new Insets(5,5,5,40));
|
||||
HBox.setMargin(offline, new Insets(5,5,5,5));
|
||||
online.setSelected(true);
|
||||
group.selectedToggleProperty().addListener((e) -> {
|
||||
group.selectedToggleProperty().addListener(e -> {
|
||||
((Fc2FollowedUpdateService)updateService).setShowOnline(online.isSelected());
|
||||
queue.clear();
|
||||
updateService.restart();
|
||||
|
|
|
@ -6,7 +6,6 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import ctbrec.Config;
|
||||
|
@ -34,54 +33,58 @@ public class Fc2FollowedUpdateService extends PaginatedScheduledService {
|
|||
return new Task<List<Model>>() {
|
||||
@Override
|
||||
public List<Model> call() throws IOException {
|
||||
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<>();
|
||||
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());
|
||||
}
|
||||
}
|
||||
return loadModels();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void setShowOnline(boolean online) {
|
||||
//this.online = online;
|
||||
private List<Model> loadModels() throws IOException {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package ctbrec.ui.sites.fc2live;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Settings;
|
||||
import ctbrec.sites.fc2live.Fc2Live;
|
||||
import ctbrec.ui.DesktopIntegration;
|
||||
import ctbrec.ui.settings.SettingsTab;
|
||||
|
@ -25,15 +24,15 @@ public class Fc2LiveConfigUI extends AbstractConfigUI {
|
|||
|
||||
@Override
|
||||
public Parent createConfigPanel() {
|
||||
GridPane layout = SettingsTab.createGridLayout();
|
||||
Settings settings = Config.getInstance().getSettings();
|
||||
var layout = SettingsTab.createGridLayout();
|
||||
var settings = Config.getInstance().getSettings();
|
||||
|
||||
int row = 0;
|
||||
Label l = new Label("Active");
|
||||
var row = 0;
|
||||
var l = new Label("Active");
|
||||
layout.add(l, 0, row);
|
||||
CheckBox enabled = new CheckBox();
|
||||
var enabled = new CheckBox();
|
||||
enabled.setSelected(!settings.disabledSites.contains(fc2live.getName()));
|
||||
enabled.setOnAction((e) -> {
|
||||
enabled.setOnAction(e -> {
|
||||
if(enabled.isSelected()) {
|
||||
settings.disabledSites.remove(fc2live.getName());
|
||||
} else {
|
||||
|
@ -45,7 +44,7 @@ public class Fc2LiveConfigUI extends AbstractConfigUI {
|
|||
layout.add(enabled, 1, 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) -> {
|
||||
if(!n.equals(Config.getInstance().getSettings().fc2liveUsername)) {
|
||||
Config.getInstance().getSettings().fc2liveUsername = username.getText();
|
||||
|
@ -59,7 +58,7 @@ public class Fc2LiveConfigUI extends AbstractConfigUI {
|
|||
layout.add(username, 1, row++);
|
||||
|
||||
layout.add(new Label("FC2Live Password"), 0, row);
|
||||
PasswordField password = new PasswordField();
|
||||
var password = new PasswordField();
|
||||
password.setText(settings.fc2livePassword);
|
||||
password.textProperty().addListener((ob, o, n) -> {
|
||||
if(!n.equals(Config.getInstance().getSettings().fc2livePassword)) {
|
||||
|
@ -73,9 +72,9 @@ public class Fc2LiveConfigUI extends AbstractConfigUI {
|
|||
GridPane.setColumnSpan(password, 2);
|
||||
layout.add(password, 1, row++);
|
||||
|
||||
Button createAccount = new Button("Create new Account");
|
||||
createAccount.setOnAction((e) -> DesktopIntegration.open(fc2live.getAffiliateLink()));
|
||||
layout.add(createAccount, 1, row++);
|
||||
var createAccount = new Button("Create new Account");
|
||||
createAccount.setOnAction(e -> DesktopIntegration.open(fc2live.getAffiliateLink()));
|
||||
layout.add(createAccount, 1, row);
|
||||
GridPane.setColumnSpan(createAccount, 2);
|
||||
GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||
GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||
|
|
|
@ -9,7 +9,7 @@ import ctbrec.ui.tabs.ThumbOverviewTab;
|
|||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Tab;
|
||||
|
||||
public class Fc2TabProvider extends TabProvider {
|
||||
public class Fc2TabProvider implements TabProvider {
|
||||
|
||||
private Fc2Live fc2live;
|
||||
private Fc2FollowedTab followed;
|
||||
|
@ -31,8 +31,8 @@ public class Fc2TabProvider extends TabProvider {
|
|||
}
|
||||
|
||||
private Tab createTab(String title, String url) {
|
||||
Fc2UpdateService updateService = new Fc2UpdateService(url, fc2live);
|
||||
ThumbOverviewTab tab = new ThumbOverviewTab(title, updateService, fc2live);
|
||||
var updateService = new Fc2UpdateService(url, fc2live);
|
||||
var tab = new ThumbOverviewTab(title, updateService, fc2live);
|
||||
tab.setRecorder(fc2live.getRecorder());
|
||||
return tab;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -22,7 +21,6 @@ import ctbrec.ui.tabs.PaginatedScheduledService;
|
|||
import javafx.concurrent.Task;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class Fc2UpdateService extends PaginatedScheduledService {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Fc2UpdateService.class);
|
||||
|
@ -41,7 +39,7 @@ public class Fc2UpdateService extends PaginatedScheduledService {
|
|||
return new Task<List<Model>>() {
|
||||
@Override
|
||||
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()
|
||||
.url(url)
|
||||
.method("POST", body)
|
||||
|
@ -52,31 +50,31 @@ public class Fc2UpdateService extends PaginatedScheduledService {
|
|||
.header(X_REQUESTED_WITH, XML_HTTP_REQUEST)
|
||||
.build();
|
||||
LOG.debug("Fetching page {}", url);
|
||||
try(Response resp = fc2live.getHttpClient().execute(req)) {
|
||||
if(resp.isSuccessful()) {
|
||||
try (var resp = fc2live.getHttpClient().execute(req)) {
|
||||
if (resp.isSuccessful()) {
|
||||
List<Fc2Model> models = new ArrayList<>();
|
||||
String msg = resp.body().string();
|
||||
JSONObject json = new JSONObject(msg);
|
||||
JSONArray channels = json.getJSONArray("channel");
|
||||
for (int i = 0; i < channels.length(); i++) {
|
||||
JSONObject channel = channels.getJSONObject(i);
|
||||
var msg = resp.body().string();
|
||||
var json = new JSONObject(msg);
|
||||
var channels = json.getJSONArray("channel");
|
||||
for (var i = 0; i < channels.length(); i++) {
|
||||
var channel = channels.getJSONObject(i);
|
||||
Fc2Model model = (Fc2Model) fc2live.createModel(channel.getString("name"));
|
||||
model.setId(channel.getString("id"));
|
||||
model.setUrl(Fc2Live.BASE_URL + '/' + model.getId());
|
||||
String previewUrl = channel.getString("image");
|
||||
if(previewUrl == null || previewUrl.trim().isEmpty()) {
|
||||
var previewUrl = channel.getString("image");
|
||||
if (previewUrl == null || previewUrl.trim().isEmpty()) {
|
||||
previewUrl = getClass().getResource("/image_not_found.png").toString();
|
||||
}
|
||||
model.setPreview(previewUrl);
|
||||
model.setDescription(channel.optString("title"));
|
||||
model.setViewerCount(channel.optInt("count"));
|
||||
if(channel.getInt("login") == 0) {
|
||||
if (channel.getInt("login") == 0) {
|
||||
models.add(model);
|
||||
}
|
||||
}
|
||||
return models.stream()
|
||||
.sorted((m1, m2) -> m2.getViewerCount() - m1.getViewerCount())
|
||||
.skip( (long)(page - 1) * modelsPerPage)
|
||||
.skip((long) (page - 1) * modelsPerPage)
|
||||
.limit(modelsPerPage)
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package ctbrec.ui.sites.flirt4free;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Settings;
|
||||
import ctbrec.sites.flirt4free.Flirt4Free;
|
||||
import ctbrec.ui.DesktopIntegration;
|
||||
import ctbrec.ui.settings.SettingsTab;
|
||||
|
@ -25,15 +24,15 @@ public class Flirt4FreeConfigUI extends AbstractConfigUI {
|
|||
|
||||
@Override
|
||||
public Parent createConfigPanel() {
|
||||
GridPane layout = SettingsTab.createGridLayout();
|
||||
Settings settings = Config.getInstance().getSettings();
|
||||
var layout = SettingsTab.createGridLayout();
|
||||
var settings = Config.getInstance().getSettings();
|
||||
|
||||
int row = 0;
|
||||
Label l = new Label("Active");
|
||||
var row = 0;
|
||||
var l = new Label("Active");
|
||||
layout.add(l, 0, row);
|
||||
CheckBox enabled = new CheckBox();
|
||||
var enabled = new CheckBox();
|
||||
enabled.setSelected(!settings.disabledSites.contains(flirt4free.getName()));
|
||||
enabled.setOnAction((e) -> {
|
||||
enabled.setOnAction(e -> {
|
||||
if(enabled.isSelected()) {
|
||||
settings.disabledSites.remove(flirt4free.getName());
|
||||
} else {
|
||||
|
@ -45,7 +44,7 @@ public class Flirt4FreeConfigUI extends AbstractConfigUI {
|
|||
layout.add(enabled, 1, 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) -> {
|
||||
if(!n.equals(Config.getInstance().getSettings().flirt4freeUsername)) {
|
||||
Config.getInstance().getSettings().flirt4freeUsername = username.getText();
|
||||
|
@ -59,7 +58,7 @@ public class Flirt4FreeConfigUI extends AbstractConfigUI {
|
|||
layout.add(username, 1, row++);
|
||||
|
||||
layout.add(new Label("Flirt4Free Password"), 0, row);
|
||||
PasswordField password = new PasswordField();
|
||||
var password = new PasswordField();
|
||||
password.setText(settings.flirt4freePassword);
|
||||
password.textProperty().addListener((ob, o, n) -> {
|
||||
if(!n.equals(Config.getInstance().getSettings().flirt4freePassword)) {
|
||||
|
@ -73,9 +72,9 @@ public class Flirt4FreeConfigUI extends AbstractConfigUI {
|
|||
GridPane.setColumnSpan(password, 2);
|
||||
layout.add(password, 1, row++);
|
||||
|
||||
Button createAccount = new Button("Create new Account");
|
||||
createAccount.setOnAction((e) -> DesktopIntegration.open(flirt4free.getAffiliateLink()));
|
||||
layout.add(createAccount, 1, row++);
|
||||
var createAccount = new Button("Create new Account");
|
||||
createAccount.setOnAction(e -> DesktopIntegration.open(flirt4free.getAffiliateLink()));
|
||||
layout.add(createAccount, 1, row);
|
||||
GridPane.setColumnSpan(createAccount, 2);
|
||||
GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||
GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||
|
|
|
@ -15,10 +15,8 @@ public class Flirt4FreeFavoritesTab extends ThumbOverviewTab implements Followed
|
|||
|
||||
public void setScene(Scene scene) {
|
||||
scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
||||
if(this.isSelected()) {
|
||||
if(event.getCode() == KeyCode.DELETE) {
|
||||
follow(selectedThumbCells, false);
|
||||
}
|
||||
if (this.isSelected() && event.getCode() == KeyCode.DELETE) {
|
||||
follow(selectedThumbCells, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import ctbrec.ui.SiteUiFactory;
|
|||
import ctbrec.ui.tabs.PaginatedScheduledService;
|
||||
import javafx.concurrent.Task;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class Flirt4FreeFavoritesUpdateService extends PaginatedScheduledService {
|
||||
private Flirt4Free flirt4free;
|
||||
|
@ -35,45 +34,49 @@ public class Flirt4FreeFavoritesUpdateService extends PaginatedScheduledService
|
|||
return new Task<List<Model>>() {
|
||||
@Override
|
||||
public List<Model> call() 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();
|
||||
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());
|
||||
}
|
||||
}
|
||||
return loadModelList();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import javafx.scene.Scene;
|
|||
import javafx.scene.control.Tab;
|
||||
import javafx.util.Duration;
|
||||
|
||||
public class Flirt4FreeTabProvider extends TabProvider {
|
||||
public class Flirt4FreeTabProvider implements TabProvider {
|
||||
|
||||
private Flirt4Free flirt4Free;
|
||||
private ThumbOverviewTab followedTab;
|
||||
|
@ -40,8 +40,8 @@ public class Flirt4FreeTabProvider extends TabProvider {
|
|||
}
|
||||
|
||||
private ThumbOverviewTab createTab(String title, String url, Predicate<Flirt4FreeModel> filter) {
|
||||
Flirt4FreeUpdateService s = new Flirt4FreeUpdateService(flirt4Free, url, filter);
|
||||
ThumbOverviewTab tab = new ThumbOverviewTab(title, s, flirt4Free);
|
||||
var s = new Flirt4FreeUpdateService(flirt4Free, url, filter);
|
||||
var tab = new ThumbOverviewTab(title, s, flirt4Free);
|
||||
tab.setRecorder(flirt4Free.getRecorder());
|
||||
s.setPeriod(Duration.seconds(60));
|
||||
return tab;
|
||||
|
|
|
@ -6,11 +6,9 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -45,11 +43,11 @@ public class Flirt4FreeUpdateService extends PaginatedScheduledService {
|
|||
@Override
|
||||
public List<Model> call() throws IOException {
|
||||
LOG.debug("Fetching page {}", url);
|
||||
Request request = new Request.Builder()
|
||||
var request = new Request.Builder()
|
||||
.url(url)
|
||||
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
||||
.build();
|
||||
try (Response response = flirt4Free.getHttpClient().execute(request)) {
|
||||
try (var response = flirt4Free.getHttpClient().execute(request)) {
|
||||
if (response.isSuccessful()) {
|
||||
return parseResponse(response);
|
||||
} else {
|
||||
|
@ -62,26 +60,24 @@ public class Flirt4FreeUpdateService extends PaginatedScheduledService {
|
|||
|
||||
private List<Model> parseResponse(Response response) throws IOException {
|
||||
List<Flirt4FreeModel> models = new ArrayList<>();
|
||||
String body = response.body().string();
|
||||
Matcher m = Pattern.compile("window\\.__homePageData__ = (\\{.*\\})", Pattern.DOTALL).matcher(body);
|
||||
var body = response.body().string();
|
||||
var m = Pattern.compile("window\\.__homePageData__ = (\\{.*\\})", Pattern.DOTALL).matcher(body);
|
||||
if (m.find()) {
|
||||
JSONObject data = new JSONObject(m.group(1));
|
||||
JSONArray modelData = data.getJSONArray("models");
|
||||
var data = new JSONObject(m.group(1));
|
||||
var modelData = data.getJSONArray("models");
|
||||
LOG.debug("Found {} models", modelData.length());
|
||||
for (int i = 0; i < modelData.length(); i++) {
|
||||
JSONObject modelJson = modelData.getJSONObject(i);
|
||||
for (var i = 0; i < modelData.length(); i++) {
|
||||
var modelJson = modelData.getJSONObject(i);
|
||||
try {
|
||||
Flirt4FreeModel model = parseModel(modelJson);
|
||||
if (model != null) {
|
||||
models.add(model);
|
||||
}
|
||||
models.add(model);
|
||||
} catch(Exception e) {
|
||||
LOG.warn("Couldn't parse model {}", modelJson);
|
||||
}
|
||||
}
|
||||
return models.stream()
|
||||
.filter(filter)
|
||||
.skip((page - 1) * MODELS_PER_PAGE)
|
||||
.skip((page - 1) * (long)MODELS_PER_PAGE)
|
||||
.limit(MODELS_PER_PAGE)
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
|
@ -90,14 +86,14 @@ public class Flirt4FreeUpdateService extends PaginatedScheduledService {
|
|||
}
|
||||
|
||||
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);
|
||||
model.setDisplayName(modelData.getString("display"));
|
||||
model.setDescription(modelData.getString("topic"));
|
||||
model.setUrl(Flirt4Free.BASE_URI + "/rooms/" + model.getName() + '/');
|
||||
model.setNew(modelData.optString("is_new", "0").equals("1"));
|
||||
String videoHost = modelData.getString("video_host");
|
||||
String modelId = modelData.getString("model_id");
|
||||
var videoHost = modelData.getString("video_host");
|
||||
var modelId = modelData.getString("model_id");
|
||||
model.setId(modelId);
|
||||
String streamUrl = "https://manifest.vscdns.com/manifest.m3u8.m3u8?key=nil&provider=level3&secure=true&host=" + videoHost
|
||||
+ "&model_id=" + modelId;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package ctbrec.ui.sites.jasmin;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Settings;
|
||||
import ctbrec.sites.jasmin.LiveJasmin;
|
||||
import ctbrec.ui.DesktopIntegration;
|
||||
import ctbrec.ui.settings.SettingsTab;
|
||||
|
@ -25,15 +24,15 @@ public class LiveJasminConfigUi extends AbstractConfigUI {
|
|||
|
||||
@Override
|
||||
public Parent createConfigPanel() {
|
||||
Settings settings = Config.getInstance().getSettings();
|
||||
GridPane layout = SettingsTab.createGridLayout();
|
||||
var settings = Config.getInstance().getSettings();
|
||||
var layout = SettingsTab.createGridLayout();
|
||||
|
||||
int row = 0;
|
||||
Label l = new Label("Active");
|
||||
var row = 0;
|
||||
var l = new Label("Active");
|
||||
layout.add(l, 0, row);
|
||||
CheckBox enabled = new CheckBox();
|
||||
var enabled = new CheckBox();
|
||||
enabled.setSelected(!settings.disabledSites.contains(liveJasmin.getName()));
|
||||
enabled.setOnAction((e) -> {
|
||||
enabled.setOnAction(e -> {
|
||||
if(enabled.isSelected()) {
|
||||
settings.disabledSites.remove(liveJasmin.getName());
|
||||
} else {
|
||||
|
@ -45,7 +44,7 @@ public class LiveJasminConfigUi extends AbstractConfigUI {
|
|||
layout.add(enabled, 1, 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) -> {
|
||||
if(!n.equals(Config.getInstance().getSettings().livejasminUsername)) {
|
||||
Config.getInstance().getSettings().livejasminUsername = n;
|
||||
|
@ -59,7 +58,7 @@ public class LiveJasminConfigUi extends AbstractConfigUI {
|
|||
layout.add(username, 1, row++);
|
||||
|
||||
layout.add(new Label("LiveJasmin Password"), 0, row);
|
||||
PasswordField password = new PasswordField();
|
||||
var password = new PasswordField();
|
||||
password.setText(Config.getInstance().getSettings().livejasminPassword);
|
||||
password.textProperty().addListener((ob, o, n) -> {
|
||||
if(!n.equals(Config.getInstance().getSettings().livejasminPassword)) {
|
||||
|
@ -74,7 +73,7 @@ public class LiveJasminConfigUi extends AbstractConfigUI {
|
|||
layout.add(password, 1, 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.textProperty().addListener((ob, o, n) -> {
|
||||
Config.getInstance().getSettings().livejasminBaseUrl = baseUrl.getText();
|
||||
|
@ -85,9 +84,9 @@ public class LiveJasminConfigUi extends AbstractConfigUI {
|
|||
GridPane.setColumnSpan(baseUrl, 2);
|
||||
layout.add(baseUrl, 1, row++);
|
||||
|
||||
Button createAccount = new Button("Create new Account");
|
||||
createAccount.setOnAction((e) -> DesktopIntegration.open(liveJasmin.getAffiliateLink()));
|
||||
layout.add(createAccount, 1, row++);
|
||||
var createAccount = new Button("Create new Account");
|
||||
createAccount.setOnAction(e -> DesktopIntegration.open(liveJasmin.getAffiliateLink()));
|
||||
layout.add(createAccount, 1, row);
|
||||
GridPane.setColumnSpan(createAccount, 2);
|
||||
GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||
GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||
|
|
|
@ -4,7 +4,6 @@ import java.io.IOException;
|
|||
import java.util.Collections;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -19,23 +18,24 @@ import okhttp3.HttpUrl;
|
|||
|
||||
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";
|
||||
private CookieJar cookieJar;
|
||||
private ExternalBrowser browser;
|
||||
|
||||
public LiveJasminElectronLoginDialog(CookieJar cookieJar) throws Exception {
|
||||
public LiveJasminElectronLoginDialog(CookieJar cookieJar) throws IOException {
|
||||
this.cookieJar = cookieJar;
|
||||
browser = ExternalBrowser.getInstance();
|
||||
try {
|
||||
JSONObject config = new JSONObject();
|
||||
var config = new JSONObject();
|
||||
config.put("url", URL);
|
||||
config.put("w", 640);
|
||||
config.put("h", 720);
|
||||
JSONObject msg = new JSONObject();
|
||||
var msg = new JSONObject();
|
||||
msg.put("config", config);
|
||||
browser.run(msg, msgHandler);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new IOException("Couldn't wait for login dialog", e);
|
||||
} catch (IOException 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) -> {
|
||||
//LOG.debug("Browser: {}", line);
|
||||
private Consumer<String> msgHandler = line -> {
|
||||
if(!line.startsWith("{")) {
|
||||
System.err.println(line);
|
||||
System.err.println(line); // NOSONAR
|
||||
} else {
|
||||
JSONObject json = new JSONObject(line);
|
||||
var json = new JSONObject(line);
|
||||
if(json.has("url")) {
|
||||
String url = json.getString("url");
|
||||
var url = json.getString("url");
|
||||
if(url.endsWith("/auth/login")) {
|
||||
try {
|
||||
String username = Config.getInstance().getSettings().livejasminUsername;
|
||||
|
@ -73,9 +72,9 @@ public class LiveJasminElectronLoginDialog {
|
|||
}
|
||||
}
|
||||
if(json.has("cookies")) {
|
||||
JSONArray _cookies = json.getJSONArray("cookies");
|
||||
for (int i = 0; i < _cookies.length(); i++) {
|
||||
JSONObject cookie = _cookies.getJSONObject(i);
|
||||
var cookiesFromBrowser = json.getJSONArray("cookies");
|
||||
for (var i = 0; i < cookiesFromBrowser.length(); i++) {
|
||||
var cookie = cookiesFromBrowser.getJSONObject(i);
|
||||
Builder b = new Cookie.Builder()
|
||||
.path("/")
|
||||
.domain(LiveJasmin.baseDomain)
|
||||
|
|
|
@ -15,10 +15,8 @@ public class LiveJasminFollowedTab extends LiveJasminTab implements FollowedTab
|
|||
@Override
|
||||
public void setScene(Scene scene) {
|
||||
scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
||||
if(this.isSelected()) {
|
||||
if(event.getCode() == KeyCode.DELETE) {
|
||||
follow(selectedThumbCells, false);
|
||||
}
|
||||
if (this.isSelected() && event.getCode() == KeyCode.DELETE) {
|
||||
follow(selectedThumbCells, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import ctbrec.ui.SiteUiFactory;
|
|||
import ctbrec.ui.tabs.PaginatedScheduledService;
|
||||
import javafx.concurrent.Task;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class LiveJasminFollowedUpdateService extends PaginatedScheduledService {
|
||||
|
||||
|
@ -50,16 +49,16 @@ public class LiveJasminFollowedUpdateService extends PaginatedScheduledService {
|
|||
throw new NotLoggedInExcetion("Couldn't login to livejasmin");
|
||||
}
|
||||
LOG.debug("Fetching page {}", url);
|
||||
Request request = new Request.Builder()
|
||||
var request = new Request.Builder()
|
||||
.url(url)
|
||||
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
||||
.header(ACCEPT, "*/*")
|
||||
.header(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage())
|
||||
.header(REFERER, liveJasmin.getBaseUrl())
|
||||
.build();
|
||||
try (Response response = liveJasmin.getHttpClient().execute(request)) {
|
||||
try (var response = liveJasmin.getHttpClient().execute(request)) {
|
||||
if (response.isSuccessful()) {
|
||||
String body = response.body().string();
|
||||
var body = response.body().string();
|
||||
List<Model> models = new ArrayList<>();
|
||||
Elements modelCells = getTags(body, "article[class~=perf_container]");
|
||||
for (Element modelCell : modelCells) {
|
||||
|
|
|
@ -41,7 +41,7 @@ public class LiveJasminSiteUi extends AbstractSiteUi {
|
|||
public synchronized boolean login() throws IOException {
|
||||
// renew login every 30 min
|
||||
long now = System.currentTimeMillis();
|
||||
boolean renew = false;
|
||||
var renew = false;
|
||||
if ((now - lastLoginTime) > TimeUnit.MINUTES.toMillis(30)) {
|
||||
renew = true;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@ package ctbrec.ui.sites.jasmin;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.sites.Site;
|
||||
import ctbrec.ui.tabs.PaginatedScheduledService;
|
||||
|
@ -14,6 +17,7 @@ import javafx.scene.input.KeyCode;
|
|||
import javafx.scene.input.KeyEvent;
|
||||
|
||||
public class LiveJasminTab extends ThumbOverviewTab {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(LiveJasminTab.class);
|
||||
protected Label status;
|
||||
protected Button acknowledge = new Button("That's alright");
|
||||
private boolean betaAcknowledged = Config.getInstance().getSettings().livejasminBetaAcknowledged;
|
||||
|
@ -36,6 +40,7 @@ public class LiveJasminTab extends ThumbOverviewTab {
|
|||
try {
|
||||
Config.getInstance().save();
|
||||
} catch (IOException e1) {
|
||||
LOG.error("Couldn't save config", e1);
|
||||
}
|
||||
status.setText("Loading...");
|
||||
grid.getChildren().remove(acknowledge);
|
||||
|
@ -47,11 +52,6 @@ public class LiveJasminTab extends ThumbOverviewTab {
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createGui() {
|
||||
super.createGui();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSuccess() {
|
||||
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) {
|
||||
scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
||||
if(this.isSelected()) {
|
||||
if(event.getCode() == KeyCode.DELETE) {
|
||||
follow(selectedThumbCells, false);
|
||||
}
|
||||
if (this.isSelected() && event.getCode() == KeyCode.DELETE) {
|
||||
follow(selectedThumbCells, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import javafx.scene.Scene;
|
|||
import javafx.scene.control.Tab;
|
||||
import javafx.util.Duration;
|
||||
|
||||
public class LiveJasminTabProvider extends TabProvider {
|
||||
public class LiveJasminTabProvider implements TabProvider {
|
||||
|
||||
private LiveJasmin liveJasmin;
|
||||
private LiveJasminFollowedTab followedTab;
|
||||
|
@ -43,7 +43,7 @@ public class LiveJasminTabProvider extends TabProvider {
|
|||
}
|
||||
|
||||
private ThumbOverviewTab createTab(String title, String url) {
|
||||
LiveJasminUpdateService s = new LiveJasminUpdateService(liveJasmin, url);
|
||||
var s = new LiveJasminUpdateService(liveJasmin, url);
|
||||
s.setPeriod(Duration.seconds(60));
|
||||
ThumbOverviewTab tab = new LiveJasminTab(title, s, liveJasmin);
|
||||
tab.setRecorder(liveJasmin.getRecorder());
|
||||
|
|
|
@ -8,25 +8,21 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Model;
|
||||
import ctbrec.io.CookieJarImpl;
|
||||
import ctbrec.io.HttpException;
|
||||
import ctbrec.sites.jasmin.LiveJasmin;
|
||||
import ctbrec.sites.jasmin.LiveJasminModel;
|
||||
import ctbrec.ui.SiteUI;
|
||||
import ctbrec.ui.SiteUiFactory;
|
||||
import ctbrec.ui.tabs.PaginatedScheduledService;
|
||||
import javafx.concurrent.Task;
|
||||
import okhttp3.Cookie;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class LiveJasminUpdateService extends PaginatedScheduledService {
|
||||
|
||||
|
@ -45,8 +41,8 @@ public class LiveJasminUpdateService extends PaginatedScheduledService {
|
|||
@Override
|
||||
public List<Model> call() throws IOException {
|
||||
// sort by popularity
|
||||
CookieJarImpl cookieJar = liveJasmin.getHttpClient().getCookieJar();
|
||||
Cookie sortCookie = new Cookie.Builder()
|
||||
var cookieJar = liveJasmin.getHttpClient().getCookieJar();
|
||||
var sortCookie = new Cookie.Builder()
|
||||
.domain(LiveJasmin.baseDomain)
|
||||
.name("listPageOrderType")
|
||||
.value("most_popular")
|
||||
|
@ -55,7 +51,7 @@ public class LiveJasminUpdateService extends PaginatedScheduledService {
|
|||
|
||||
// TODO find out how to switch pages
|
||||
LOG.debug("Fetching page {}", url);
|
||||
Request request = new Request.Builder()
|
||||
var request = new Request.Builder()
|
||||
.url(url)
|
||||
.addHeader(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
||||
.addHeader(ACCEPT, MIMETYPE_APPLICATION_JSON)
|
||||
|
@ -63,31 +59,16 @@ public class LiveJasminUpdateService extends PaginatedScheduledService {
|
|||
.addHeader(REFERER, liveJasmin.getBaseUrl())
|
||||
.addHeader(X_REQUESTED_WITH, XML_HTTP_REQUEST)
|
||||
.build();
|
||||
try (Response response = liveJasmin.getHttpClient().execute(request)) {
|
||||
try (var response = liveJasmin.getHttpClient().execute(request)) {
|
||||
LOG.debug("Response {} {}", response.code(), response.message());
|
||||
if (response.isSuccessful()) {
|
||||
String body = response.body().string();
|
||||
var body = response.body().string();
|
||||
List<Model> models = new ArrayList<>();
|
||||
JSONObject json = new JSONObject(body);
|
||||
//LOG.debug(json.toString(2));
|
||||
var json = new JSONObject(body);
|
||||
if(json.optBoolean("success")) {
|
||||
JSONObject data = json.getJSONObject("data");
|
||||
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);
|
||||
}
|
||||
parseModels(models, json);
|
||||
} else if(json.optString("error").equals("Please login.")) {
|
||||
SiteUI siteUI = SiteUiFactory.getUi(liveJasmin);
|
||||
var siteUI = SiteUiFactory.getUi(liveJasmin);
|
||||
if(siteUI.login()) {
|
||||
return call();
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package ctbrec.ui.sites.manyvids;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Settings;
|
||||
import ctbrec.sites.manyvids.MVLive;
|
||||
import ctbrec.ui.settings.SettingsTab;
|
||||
import ctbrec.ui.sites.AbstractConfigUI;
|
||||
|
@ -20,15 +19,15 @@ public class MVLiveConfigUi extends AbstractConfigUI {
|
|||
|
||||
@Override
|
||||
public Parent createConfigPanel() {
|
||||
Settings settings = Config.getInstance().getSettings();
|
||||
var settings = Config.getInstance().getSettings();
|
||||
GridPane layout = SettingsTab.createGridLayout();
|
||||
|
||||
int row = 0;
|
||||
Label l = new Label("Active");
|
||||
var row = 0;
|
||||
var l = new Label("Active");
|
||||
layout.add(l, 0, row);
|
||||
CheckBox enabled = new CheckBox();
|
||||
var enabled = new CheckBox();
|
||||
enabled.setSelected(!settings.disabledSites.contains(site.getName()));
|
||||
enabled.setOnAction((e) -> {
|
||||
enabled.setOnAction(e -> {
|
||||
if(enabled.isSelected()) {
|
||||
settings.disabledSites.remove(site.getName());
|
||||
} else {
|
||||
|
@ -37,7 +36,7 @@ public class MVLiveConfigUi extends AbstractConfigUI {
|
|||
save();
|
||||
});
|
||||
GridPane.setMargin(enabled, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||
layout.add(enabled, 1, row++);
|
||||
layout.add(enabled, 1, row);
|
||||
return layout;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import ctbrec.ui.tabs.ThumbOverviewTab;
|
|||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Tab;
|
||||
|
||||
public class MVLiveTabProvider extends TabProvider {
|
||||
public class MVLiveTabProvider implements TabProvider {
|
||||
|
||||
private MVLive mvlive;
|
||||
|
||||
|
@ -26,8 +26,8 @@ public class MVLiveTabProvider extends TabProvider {
|
|||
}
|
||||
|
||||
private Tab createTab(String title) {
|
||||
MVLiveUpdateService updateService = new MVLiveUpdateService(mvlive);
|
||||
ThumbOverviewTab tab = new ThumbOverviewTab(title, updateService, mvlive);
|
||||
var updateService = new MVLiveUpdateService(mvlive);
|
||||
var tab = new ThumbOverviewTab(title, updateService, mvlive);
|
||||
tab.setRecorder(mvlive.getRecorder());
|
||||
tab.setImageAspectRatio(1);
|
||||
return tab;
|
||||
|
|
|
@ -57,50 +57,59 @@ public class FriendsUpdateService extends PaginatedScheduledService {
|
|||
.build();
|
||||
try (Response resp = myFreeCams.getHttpClient().execute(req)) {
|
||||
if (resp.isSuccessful()) {
|
||||
String body = resp.body().string().substring(4);
|
||||
try {
|
||||
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);
|
||||
}
|
||||
var body = resp.body().string().substring(4);
|
||||
parseModels(body, models);
|
||||
} else {
|
||||
LOG.error("Couldn't load friends list {} {}", resp.code(), resp.message());
|
||||
}
|
||||
}
|
||||
boolean filterOnline = mode == Mode.ONLINE;
|
||||
return models.stream().filter(m -> {
|
||||
try {
|
||||
return m.isOnline() == filterOnline;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
return models.stream()
|
||||
.filter(m -> {
|
||||
try {
|
||||
return m.isOnline() == filterOnline;
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.sorted((m1, m2) -> (int) (m2.getCamScore() - m1.getCamScore()))
|
||||
.skip((page - 1) * 50l)
|
||||
.limit(50)
|
||||
.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) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ public class HDCamsUpdateService extends PaginatedScheduledService {
|
|||
return new Task<List<Model>>() {
|
||||
@Override
|
||||
public List<Model> call() throws IOException {
|
||||
MyFreeCamsClient client = MyFreeCamsClient.getInstance();
|
||||
int modelsPerPage = 50;
|
||||
var client = MyFreeCamsClient.getInstance();
|
||||
var modelsPerPage = 50;
|
||||
|
||||
return client.getModels().stream()
|
||||
.filter(m -> m.getPreview() != null)
|
||||
|
@ -33,7 +33,10 @@ public class HDCamsUpdateService extends PaginatedScheduledService {
|
|||
.filter(m -> {
|
||||
try {
|
||||
return m.isOnline();
|
||||
} catch(Exception e) {
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue