revival commit

This commit is contained in:
Tinglyyy
2026-01-18 14:54:52 +01:00
parent 52f243f3a2
commit 2b7d30810b
23 changed files with 901 additions and 66 deletions

2
.idea/vcs.xml generated
View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="" vcs="Git" />
</component>
</project>

87
pom.xml
View File

@@ -6,7 +6,7 @@
<groupId>org.openautonomousconnection</groupId>
<artifactId>WebClient</artifactId>
<version>1.0-BETA.1.0</version>
<version>1.0.0-BETA.1.1</version>
<organization>
<name>Open Autonomous Connection</name>
<url>https://open-autonomous-connection.org/</url>
@@ -45,48 +45,14 @@
<issueManagement>
<system>Issue Tracker</system>
<url>https://repo.open-autonomous-connection.org/open-autonomous-connection/WebClient/issues</url>
<url>https://repo.open-autonomous-connection.org/open-autonomous-connection/DNSServer/issues</url>
</issueManagement>
<licenses>
<license>
<name>Open Autonomous Public License (OAPL)</name>
<url>https://open-autonomous-connection.org/license.html</url>
</license>
<license>
<name>GNU General Public License v3.0</name>
<url>https://www.gnu.org/licenses/gpl-3.0.html</url>
<comments>
Default license: Applies to all users and projects unless an explicit alternative license has been granted.
</comments>
</license>
<license>
<name>LPGL 3</name>
<url>https://www.gnu.org/licenses/lgpl-3.0.html#license-text</url>
</license>
<license>
<name>LPGL 2.1</name>
<url>https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.en#SEC1</url>
</license>
<license>
<name>WTPL License</name>
<url>https://github.com/ronmamo/reflections/tree/master?tab=WTFPL-1-ov-file</url>
</license>
<license>
<name>Apache License 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
<license>
<name>MIT License</name>
<url>https://opensource.org/license/mit</url>
</license>
<license>
<name>javassist</name>
<url>https://github.com/jboss-javassist/javassist/blob/master/License.html</url>
</license>
<license>
<name>projectlombok</name>
<url>https://github.com/projectlombok/lombok?tab=License-1-ov-file</url>
<name>Open Autonomous Public License</name>
<url>https://repo.open-autonomous-connection.org/Open-Autonomous-Connection/OAPL/</url>
<distribution>repo</distribution>
</license>
</licenses>
@@ -104,7 +70,7 @@
<dependency>
<groupId>org.openautonomousconnection</groupId>
<artifactId>protocol</artifactId>
<version>1.0.0-BETA.5</version>
<version>1.0.0-BETA.5.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
@@ -112,30 +78,21 @@
<version>1.18.38</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.22.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.openautonomousconnection</groupId>
<artifactId>luascript</artifactId>
<version>1.0-BETA.1.0</version>
</dependency>
<dependency>
<groupId>org.openautonomousconnection.infonamelib</groupId>
<artifactId>InfoNameLib</artifactId>
<version>1.0.0-BETA.1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.openautonomousconnection.webclient.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,80 @@
/* Author: Maple
* Dec. 12 2025
* */
package org.openautonomousconnection.webclient;
import dev.unlegitdqrk.unlegitlibrary.event.EventManager;
import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler;
import org.openautonomousconnection.protocol.ProtocolBridge;
import org.openautonomousconnection.protocol.ProtocolSettings;
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
import org.openautonomousconnection.webclient.network.WebClient;
import org.openautonomousconnection.webclient.network.handlers.ServerPacketHandler;
import org.openautonomousconnection.webclient.packetlistener.listeners.WebPacketListener;
import org.openautonomousconnection.webclient.ui.MainFrame;
import java.beans.EventHandler;
import java.io.File;
public class Main {
public static MainFrame mainFrame;
public static final String DEFAULT_HOST = "ins.open-autonomous-connection.org";
public static final int DEFAULT_PORT = 1023;
private static final ProtocolVersion PROTOCOL_VERSION = ProtocolVersion.PV_1_0_0_BETA;
public static WebClient client;
public static ProtocolBridge bridge;
public static void main(String[] args) {
initProtocol();
try {
registerEventHandlers();
} catch (Exception e) {
throw new RuntimeException(e);
}
registerPacketListeners();
mainFrame = new MainFrame();
mainFrame.setVisible(true);
}
private static void initProtocol() {
client = new WebClient();
ProtocolSettings settings = new ProtocolSettings();
settings.packetHandler = new PacketHandler();
settings.eventManager = new EventManager();
settings.host = DEFAULT_HOST;
settings.port = DEFAULT_PORT;
try {
bridge = new ProtocolBridge(
client,
settings,
PROTOCOL_VERSION,
new File("logs")
);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void registerEventHandlers() throws Exception {
EventManager eventManager = bridge.getProtocolSettings().eventManager;
eventManager.registerListener(ServerPacketHandler.class);
}
private static void registerPacketListeners() {
ServerPacketHandler.registerPacketListener(new WebPacketListener());
}
}

View File

@@ -0,0 +1,59 @@
package org.openautonomousconnection.webclient.network;
import lombok.Getter;
import lombok.Setter;
import java.util.concurrent.*;
/**
* An object that is still waited for to be delivered by the server
*
* @param <T> type of promised object
*/
public class Promise<T> {
@Getter @Setter
private T object;
public Promise() {
}
public Promise(T object) {
this.object = object;
}
public static <T> Promise<T> yieldPromise(int timeout, T reference) {
try (ExecutorService executorService = Executors.newSingleThreadExecutor()) {
Callable<T> task = () -> {
for(int i = 0; i < timeout; i++) {
if(reference == null) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
if(reference == null)
throw new TimeoutException();
return reference;
};
Future<T> future = executorService.submit(task);
executorService.shutdown();
try {
return new Promise<>(future.get());
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
}
private Class<?> getType() {
return this.object.getClass();
}
}

View File

@@ -0,0 +1,107 @@
/* Author: Maple
* Dec. 12 2025
* */
package org.openautonomousconnection.webclient.network;
import lombok.Getter;
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.WebRequestPacket;
import org.openautonomousconnection.protocol.side.client.ProtocolClient;
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecord;
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus;
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.WebRequestMethod;
import org.openautonomousconnection.webclient.network.type.NTFType;
import org.openautonomousconnection.webclient.network.type.text.NetTransmitDocument;
import org.openautonomousconnection.webclient.network.type.NetTransmitFile;
import javax.swing.text.Document;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Uses the OAC-Protocol networking client
* Suppressing "unchecked" warnings because of generic casts
*/
@SuppressWarnings("unchecked")
public class WebClient extends ProtocolClient {
/**
* Global protocol timeout = 30 seconds
*/
public static final int TIMEOUT = 30;
public <T> void fulfillPromise(NTFType type, T object) {
if(!this.outstandingPromises.containsKey(type))
return;
Object promisedValue = this.outstandingPromises.get(type);
if(promisedValue != null)
return;
this.outstandingPromises.replace(type, object);
}
@Getter
private final Map<NTFType, Object> outstandingPromises = new HashMap<>();
private <T> Promise<? extends NetTransmitFile<T>> promise(NTFType type) {
NetTransmitFile<T> ntf = NetTransmitFile.of(type, null);
this.outstandingPromises.put(type, ntf);
return Promise.yieldPromise(TIMEOUT, ntf);
}
@Override
public void onResponse(INSResponseStatus insResponseStatus, List<INSRecord> list) {
}
public <T> Promise<? extends NetTransmitFile<T>> get(NTFType type, String path, T test) {
try {
this.getClientWebConnection().sendPacket(new WebRequestPacket(
path,
WebRequestMethod.GET,
Map.of(),
null
));
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
return this.promise(type);
}
public void post(String path) {
try {
this.getClientWebConnection().sendPacket(new WebRequestPacket(
path,
WebRequestMethod.POST,
Map.of(),
null
));
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
public Promise<NetTransmitFile<Document>> getIndex() {
try {
this.getClientWebConnection().sendPacket(new WebRequestPacket(
"index.html",
WebRequestMethod.GET,
Map.of(),
null
));
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
System.out.println(promise(NTFType.DOCUMENT).getClass().getSimpleName());
return null;//(Promise<NetTransmitFile<Document>>) promise(NTFType.DOCUMENT);
}
}

View File

@@ -0,0 +1,43 @@
/* Author: Maple
* Dec. 12 2025
* */
package org.openautonomousconnection.webclient.network.handlers;
import org.openautonomousconnection.protocol.side.client.ProtocolClient;
import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.handlers.ClassicHandlerClient;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects.Classic_Domain;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.site.Classic_SiteType;
import org.openautonomousconnection.protocol.versions.v1_0_0.classic.utils.Classic_ProtocolVersion;
/**
* Handle deprecated (classic) versions
*/
@SuppressWarnings("deprecated")
public class ClassicHandler extends ClassicHandlerClient {
public ClassicHandler(ProtocolClient client) {
super(client);
}
@Override
public void unsupportedClassicPacket(String className, Object[] objects) {
}
@Override
public void handleHTMLContent(Classic_SiteType classicSiteType, Classic_Domain classicDomain, String s) {
}
@Override
public void handleMessage(String message, Classic_ProtocolVersion classicProtocolVersion) {
}
@Override
public void validationCompleted(Classic_Domain classicDomain, INSResponseStatus insResponseStatus) {
}
}

View File

@@ -0,0 +1,35 @@
/* Author: Maple
* Jan. 16 2026
* */
package org.openautonomousconnection.webclient.network.handlers;
import dev.unlegitdqrk.unlegitlibrary.event.EventListener;
import dev.unlegitdqrk.unlegitlibrary.network.system.client.events.C_PacketReceivedEvent;
import dev.unlegitdqrk.unlegitlibrary.network.system.packets.Packet;
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.AuthPacket;
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.WebResponsePacket;
import org.openautonomousconnection.webclient.packetlistener.PacketListener;
import java.util.ArrayList;
import java.util.List;
public class ServerPacketHandler extends EventListener {
private static final List<PacketListener> listeners = new ArrayList<>();
public static void registerPacketListener(PacketListener packetListener) {
listeners.add(packetListener);
}
public void onPacketReceived(C_PacketReceivedEvent packetReceivedEvent) {
Packet packet = packetReceivedEvent.getPacket();
switch (packet.getPacketID()) {
case 4 -> listeners
.forEach(l -> l.onAuthPacketReceived((AuthPacket) packet));
case 9 -> listeners
.forEach(l -> l.onWebResponsePacketReceived((WebResponsePacket) packet));}
}
}

View File

@@ -0,0 +1,13 @@
/* Author: Maple
* Jan. 17 2026
* */
package org.openautonomousconnection.webclient.network.type;
public enum NTFType {
UNKNOWN,
STYLESHEET,
DOCUMENT,
ICON,
FILE
}

View File

@@ -0,0 +1,34 @@
/* Author: Maple
* Jan. 17 2026
* */
package org.openautonomousconnection.webclient.network.type;
import org.jsoup.nodes.Document;
import org.openautonomousconnection.webclient.network.type.application.NetAppstreamFile;
import org.openautonomousconnection.webclient.network.type.image.NetTransmitIcon;
import org.openautonomousconnection.webclient.network.type.text.NetTransmitDocument;
import org.openautonomousconnection.webclient.network.type.text.NetTransmitStylesheet;
import org.w3c.dom.css.CSSStyleSheet;
import javax.swing.*;
import java.io.File;
public interface NetTransmitFile<T> {
T getNtf();
void setNtf(T ntf);
@SuppressWarnings("unchecked")
static <T> NetTransmitFile<T> of(NTFType type, T ntf) {
return (NetTransmitFile<T>) switch (type) {
case FILE -> new NetAppstreamFile((File) ntf);
case ICON -> new NetTransmitIcon((ImageIcon) ntf);
case DOCUMENT -> new NetTransmitDocument((Document) ntf);
case STYLESHEET -> new NetTransmitStylesheet((CSSStyleSheet) ntf);
case null, default -> new NetTransmitUnknown(ntf);
};
}
}

View File

@@ -0,0 +1,20 @@
/* Author: Maple
* Jan. 17 2026
* */
package org.openautonomousconnection.webclient.network.type;
import lombok.Getter;
import lombok.Setter;
public class NetTransmitUnknown implements NetTransmitFile<Object> {
@Getter @Setter
private Object ntf;
public NetTransmitUnknown() {
}
public NetTransmitUnknown(Object ntf) {
this.ntf = ntf;
}
}

View File

@@ -0,0 +1,25 @@
/* Author: Maple
* Jan. 17 2026
* */
package org.openautonomousconnection.webclient.network.type.application;
import lombok.Getter;
import lombok.Setter;
import org.openautonomousconnection.webclient.network.type.NetTransmitFile;
import java.io.File;
public class NetAppstreamFile implements NetTransmitFile<File> {
@Getter
@Setter
private File ntf;
public NetAppstreamFile() {
}
public NetAppstreamFile(File ntf) {
this.ntf = ntf;
}
}

View File

@@ -0,0 +1,25 @@
/* Author: Maple
* Jan. 17 2026
* */
package org.openautonomousconnection.webclient.network.type.image;
import lombok.Getter;
import lombok.Setter;
import org.openautonomousconnection.webclient.network.type.NetTransmitFile;
import javax.swing.*;
public class NetTransmitIcon implements NetTransmitFile<ImageIcon> {
@Getter
@Setter
private ImageIcon ntf;
public NetTransmitIcon() {
}
public NetTransmitIcon(ImageIcon ntf) {
this.ntf = ntf;
}
}

View File

@@ -0,0 +1,23 @@
/* Author: Maple
* Jan. 17 2026
* */
package org.openautonomousconnection.webclient.network.type.text;
import lombok.Getter;
import lombok.Setter;
import org.jsoup.nodes.Document;
import org.openautonomousconnection.webclient.network.type.NetTransmitFile;
public class NetTransmitDocument implements NetTransmitFile<Document> {
@Getter @Setter
private Document ntf;
public NetTransmitDocument() {
}
public NetTransmitDocument(Document ntf) {
this.ntf = ntf;
}
}

View File

@@ -0,0 +1,25 @@
/* Author: Maple
* Jan. 17 2026
* */
package org.openautonomousconnection.webclient.network.type.text;
import lombok.Getter;
import lombok.Setter;
import org.openautonomousconnection.webclient.network.type.NetTransmitFile;
import org.w3c.dom.css.CSSStyleSheet;
public class NetTransmitStylesheet implements NetTransmitFile<CSSStyleSheet> {
@Getter
@Setter
private CSSStyleSheet ntf;
public NetTransmitStylesheet() {
}
public NetTransmitStylesheet(CSSStyleSheet ntf) {
this.ntf = ntf;
}
}

View File

@@ -0,0 +1,104 @@
/* Author: Maple
* Dec. 12 2025
* */
package org.openautonomousconnection.webclient.network.website;
import lombok.Getter;
import lombok.Setter;
import org.jsoup.nodes.Document;
import org.openautonomousconnection.webclient.Main;
import org.openautonomousconnection.webclient.network.Promise;
import org.openautonomousconnection.webclient.network.type.NTFType;
import org.openautonomousconnection.webclient.network.type.NetTransmitFile;
import javax.annotation.Nullable;
import javax.swing.*;
import java.net.URL;
import java.util.Objects;
/**
* Contains data about a site
* Suppressing "unchecked" warnings because of generic casts
*/
@SuppressWarnings("unchecked")
public final class WebSite {
@Getter
private final URL infoName;
@Getter @Setter
private Document dom;
/**
*
*/
public WebSite(URL infoName) {
this.infoName = infoName;
}
/**
* Send new get request
*/
public Document requestNewDom() {
Document test = null;
Promise<NetTransmitFile<Document>> promise = (Promise<NetTransmitFile<Document>>)
Main.client.get(NTFType.DOCUMENT, this.infoName.getPath().toString(), test);
return promise.getObject().getNtf();
}
/**
* Get favicon of site by attempting to retrieve the favicon.ico
*
* @return retrieved icon or null
*/
public Icon getFavIcon() {
return getFavIcon(this.infoName);
}
/**
* Get favicon of site by attempting to retrieve the favicon.ico
*
* @param infoName info name that leads to the site with the favicon
* @return retrieved icon or null
*/
public static @Nullable Icon getFavIcon(URL infoName) {
ImageIcon test = null;
Promise<NetTransmitFile<ImageIcon>> promise = (Promise<NetTransmitFile<ImageIcon>>)
Main.client.get(NTFType.ICON, infoName.getPath().toString(), test);
return promise.getObject().getNtf();
}
// /**
// * Get HTML text (dom) of site
// *
// * @param infoName that leads to the target OAC page
// * @return html document
// */
// public static Document getDom(InfoName infoName) {
// Main.client.getDocument();
// }
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (WebSite) obj;
return Objects.equals(this.infoName, that.infoName);
}
@Override
public int hashCode() {
return Objects.hash(infoName);
}
@Override
public String toString() {
return "WebSite{" +
"infoName=" + this.infoName +
", dom=" + this.dom +
'}';
}
}

View File

@@ -0,0 +1,68 @@
/* Author: Maple
* Dec. 12 2025
* */
package org.openautonomousconnection.webclient.network.website.tab;
import lombok.Getter;
import lombok.Setter;
import org.openautonomousconnection.webclient.network.website.WebSite;
import javax.swing.*;
import java.net.URL;
import java.util.Objects;
@Getter @Setter
public final class Tab {
private URL infoName;
private Icon favicon;
private WebSite webSite;
public Tab(URL infoName, Icon favicon) {
this.infoName = infoName;
this.favicon = favicon;
this.webSite = new WebSite(infoName);
}
public Tab(URL infoName) {
this.infoName = infoName;
this.favicon = WebSite.getFavIcon(infoName);
this.webSite = new WebSite(infoName);
}
public Tab(WebSite webSite) {
this.infoName = webSite.getInfoName();
this.favicon = webSite.getFavIcon();
this.webSite = webSite;
}
public void refresh() {
this.webSite.requestNewDom();
this.favicon = this.webSite.getFavIcon();
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (Tab) obj;
return Objects.equals(this.infoName, that.infoName) &&
Objects.equals(this.favicon, that.favicon) &&
Objects.equals(this.webSite, that.webSite);
}
@Override
public int hashCode() {
return Objects.hash(this.infoName, this.favicon, this.webSite);
}
@Override
public String toString() {
return "Tab{" +
"infoName=" + this.infoName +
", favicon=" + this.favicon +
", webSite=" + this.webSite +
'}';
}
}

View File

@@ -0,0 +1,24 @@
/* Author: Maple
* Jan. 16 2026
* */
package org.openautonomousconnection.webclient.packetlistener;
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.AuthPacket;
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.WebRequestPacket;
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.WebResponsePacket;
public abstract class PacketListener {
public void onAuthPacketReceived(AuthPacket authPacket) {
}
public void onAuthPacketSent(AuthPacket authPacket) {
}
public void onWebResponsePacketReceived(WebResponsePacket webResponsePacket) {
}
public void onWebRequestPacketSent(WebRequestPacket webRequestPacket) {
}
}

View File

@@ -0,0 +1,62 @@
/* Author: Maple
* Jan. 16 2026
* */
package org.openautonomousconnection.webclient.packetlistener.listeners;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.WebResponsePacket;
import org.openautonomousconnection.webclient.Main;
import org.openautonomousconnection.webclient.network.type.NTFType;
import org.openautonomousconnection.webclient.network.type.NetTransmitFile;
import org.openautonomousconnection.webclient.network.type.image.NetTransmitIcon;
import org.openautonomousconnection.webclient.network.type.text.NetTransmitDocument;
import org.openautonomousconnection.webclient.network.website.tab.Tab;
import org.openautonomousconnection.webclient.packetlistener.PacketListener;
import javax.swing.*;
public class WebPacketListener extends PacketListener {
@Override
public void onWebResponsePacketReceived(WebResponsePacket packet) {
NTFType type = NTFType.UNKNOWN;
NetTransmitFile<?> file = null;
/*
full list of content types at https://repo.open-autonomous-connection.org/open-autonomous-connection/WebServer/src/branch/master/src/main/java/org/openautonomousconnection/webserver/ContentTypeResolver.java
*/
switch (packet.getContentType()) {
case "text/html":
type = NTFType.DOCUMENT;
// body is sent as byte array (string)
String htmlText = new String(packet.getBody());
Document dom = Jsoup.parse(htmlText);
file = new NetTransmitDocument();
break;
case "image/png": // TODO: Implement
break;
case "image/ico": // the server doesn't implement this yet, so favicons won't work at this moment
type = NTFType.ICON;
ImageIcon icon = new ImageIcon(packet.getBody());
file = new NetTransmitIcon(icon);
break;
// the same as application/octet-stream
default:
break; //TODO: stream files
}
Main.client.fulfillPromise(type, file);
}
}

View File

@@ -0,0 +1,13 @@
/* Author: Maple
* Dec. 12 2025
* */
package org.openautonomousconnection.webclient.ui;
import javax.swing.*;
public abstract class BrowserFrame extends JFrame {
public BrowserFrame() {
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}

View File

@@ -0,0 +1,10 @@
/* Author: Maple
* Dec. 12 2025
* */
package org.openautonomousconnection.webclient.ui;
import javax.swing.*;
public class DOMPanel extends JPanel {
}

View File

@@ -0,0 +1,28 @@
/* Author: Maple
* Dec. 12 2025
* */
package org.openautonomousconnection.webclient.ui;
import lombok.Getter;
import org.openautonomousconnection.webclient.network.website.tab.Tab;
import java.net.MalformedURLException;
import java.net.URI;
public final class MainFrame extends BrowserFrame{
@Getter
private Tab openTab;
public MainFrame() {
this.setSize(800, 600);
try {
this.openTab = new Tab(
URI.create("web://open-autonomous-connection.org").toURL()
);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -0,0 +1,31 @@
/* Author: Maple
* Dec. 12 2025
* */
package org.openautonomousconnection.webclient.ui.tab;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import org.openautonomousconnection.webclient.network.website.tab.Tab;
import javax.swing.*;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
/**
* Button that contains Tab data
*/
@Getter @Setter
public class TabButton extends JButton {
private Tab tab;
public TabButton(@NonNull String infoName) throws MalformedURLException {
this(URI.create(infoName).toURL());
}
public TabButton(@NonNull URL infoName) {
this.tab = new Tab(infoName);
}
}

View File

@@ -0,0 +1,49 @@
/* Author: Maple
* Dec. 12 2025
* */
package org.openautonomousconnection.webclient.ui.tab;
import lombok.Getter;
import javax.swing.*;
import java.awt.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* View at the top of the screen that contains the tabs
*/
public class TabButtonView extends JPanel {
@Getter
private final List<TabButton> tabButtons;
public TabButtonView() {
this(Collections.emptyList());
}
/**
* Constructor with preset buttons
* @param tabButtons already created buttons
*/
public TabButtonView(Collection<TabButton> tabButtons) {
this.tabButtons = (List<TabButton>) tabButtons;
FlowLayout layoutStyle = new FlowLayout(FlowLayout.LEFT, 0, 0);
this.setLayout(layoutStyle);
}
public void addButton(TabButton tabButton) {
this.tabButtons.add(tabButton);
}
public TabButton getButton(int index) {
return this.tabButtons.get(index);
}
}