diff --git a/client/src/main/java/nl/andrewlalis/aos_client/launcher/servers/PublicServerInfo.java b/client/src/main/java/nl/andrewlalis/aos_client/launcher/servers/PublicServerInfo.java index e72d320..89aab05 100644 --- a/client/src/main/java/nl/andrewlalis/aos_client/launcher/servers/PublicServerInfo.java +++ b/client/src/main/java/nl/andrewlalis/aos_client/launcher/servers/PublicServerInfo.java @@ -45,6 +45,7 @@ public record PublicServerInfo( panel.add(addressLabel, c); c.gridy++; JTextArea descriptionArea = new JTextArea(value.description()); + descriptionArea.setFont(new Font("monospaced", Font.PLAIN, 12)); descriptionArea.setEditable(false); descriptionArea.setWrapStyleWord(true); descriptionArea.setLineWrap(true); @@ -64,6 +65,8 @@ public record PublicServerInfo( descriptionArea.setBackground(list.getBackground()); } + panel.revalidate(); + return panel; }; } diff --git a/client/src/main/java/nl/andrewlalis/aos_client/launcher/servers/PublicServerListModel.java b/client/src/main/java/nl/andrewlalis/aos_client/launcher/servers/PublicServerListModel.java index 6d24c89..0b0264e 100644 --- a/client/src/main/java/nl/andrewlalis/aos_client/launcher/servers/PublicServerListModel.java +++ b/client/src/main/java/nl/andrewlalis/aos_client/launcher/servers/PublicServerListModel.java @@ -23,7 +23,9 @@ import java.util.Iterator; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; public class PublicServerListModel extends AbstractListModel { private final List currentPageItems; @@ -38,14 +40,12 @@ public class PublicServerListModel extends AbstractListModel { private final HttpClient client; private final ObjectMapper mapper; private final ScheduledExecutorService executorService; + private ScheduledFuture pageFetchFuture; + private final List> modelUpdateListeners; - private final JButton prevButton; - private final JButton nextButton; - - public PublicServerListModel(JButton prevButton, JButton nextButton) { + public PublicServerListModel() { this.currentPageItems = new ArrayList<>(); - this.prevButton = prevButton; - this.nextButton = nextButton; + this.modelUpdateListeners = new ArrayList<>(); this.executorService = Executors.newSingleThreadScheduledExecutor(); this.client = HttpClient.newBuilder() .executor(this.executorService) @@ -53,14 +53,21 @@ public class PublicServerListModel extends AbstractListModel { .build(); this.mapper = new ObjectMapper(); this.fetchPage(0, null, null, null); - this.executorService.scheduleAtFixedRate( - () -> this.fetchPage(this.currentPage, this.currentQuery, this.currentOrder, this.currentOrderDir), - 5, - 5, - TimeUnit.SECONDS + } + + public void scheduleAutoPageFetch() { + this.pageFetchFuture = this.executorService.scheduleAtFixedRate( + () -> this.fetchPage(this.currentPage, this.currentQuery, this.currentOrder, this.currentOrderDir), + 5, + 5, + TimeUnit.SECONDS ); } + public void addListener(Consumer listener) { + this.modelUpdateListeners.add(listener); + } + public void fetchPage(int page) { this.fetchPage(page, this.currentQuery); } @@ -70,6 +77,10 @@ public class PublicServerListModel extends AbstractListModel { } public void fetchPage(int page, String query, String order, String orderDir) { + System.out.println("Fetching..."); + if (this.pageFetchFuture != null && !this.pageFetchFuture.isDone()) { + this.pageFetchFuture.cancel(false); + } String uri = "http://localhost:8567/serverInfo?page=" + page + "&size=" + this.pageSize; if (query != null && !query.isBlank()) { uri += "&q=" + URLEncoder.encode(query, StandardCharsets.UTF_8); @@ -88,29 +99,35 @@ public class PublicServerListModel extends AbstractListModel { return; } - this.client.sendAsync(request, HttpResponse.BodyHandlers.ofInputStream()).thenAcceptAsync(response -> { - if (response.statusCode() != 200) { + var requestFuture = this.client.sendAsync(request, HttpResponse.BodyHandlers.ofInputStream()); + requestFuture.whenCompleteAsync((response, throwable) -> { + this.currentPageItems.clear(); + this.firstPage = true; + this.lastPage = true; + if (throwable != null) { + System.err.println("Could not request data from registry: " + throwable); + } else if (response.statusCode() != 200) { System.err.println("Non-OK status code: " + response.statusCode()); - } - try { - JsonNode json = this.mapper.readValue(response.body(), JsonNode.class); - this.firstPage = json.get("firstPage").asBoolean(); - this.prevButton.setEnabled(!this.firstPage); - this.lastPage = json.get("lastPage").asBoolean(); - this.nextButton.setEnabled(!this.lastPage); - this.currentPage = json.get("currentPage").asInt(); - this.pageSize = json.get("pageSize").asInt(); - this.currentQuery = query; - this.currentOrder = json.get("order").asText(); - this.currentOrderDir = json.get("orderDirection").asText(); - this.currentPageItems.clear(); - for (Iterator it = json.get("contents").elements(); it.hasNext();) { - this.addServerInfoFromJson(it.next()); + } else { + try { + JsonNode json = this.mapper.readValue(response.body(), JsonNode.class); + this.firstPage = json.get("firstPage").asBoolean(); + this.lastPage = json.get("lastPage").asBoolean(); + this.currentPage = json.get("currentPage").asInt(); + this.pageSize = json.get("pageSize").asInt(); + this.currentQuery = query; + this.currentOrder = json.get("order").asText(); + this.currentOrderDir = json.get("orderDirection").asText(); + for (Iterator it = json.get("contents").elements(); it.hasNext(); ) { + this.addServerInfoFromJson(it.next()); + } + this.scheduleAutoPageFetch(); + } catch (IOException e) { + e.printStackTrace(); } - this.fireContentsChanged(this, 0, this.getSize()); - } catch (IOException e) { - e.printStackTrace(); } + this.fireContentsChanged(this, 0, this.getSize()); + this.modelUpdateListeners.forEach(l -> l.accept(this)); }); } @@ -160,6 +177,7 @@ public class PublicServerListModel extends AbstractListModel { } public void dispose() { + this.modelUpdateListeners.clear(); this.executorService.shutdown(); } } diff --git a/client/src/main/java/nl/andrewlalis/aos_client/launcher/servers/SearchServersDialog.java b/client/src/main/java/nl/andrewlalis/aos_client/launcher/servers/SearchServersDialog.java index a757b11..ea0b4df 100644 --- a/client/src/main/java/nl/andrewlalis/aos_client/launcher/servers/SearchServersDialog.java +++ b/client/src/main/java/nl/andrewlalis/aos_client/launcher/servers/SearchServersDialog.java @@ -11,8 +11,6 @@ import java.awt.event.MouseEvent; import java.io.IOException; public class SearchServersDialog extends JDialog { - private final JButton prevButton; - private final JButton nextButton; private final PublicServerListModel listModel; public SearchServersDialog(Frame frame, ServerInfoListModel serverInfoListModel) { @@ -20,9 +18,7 @@ public class SearchServersDialog extends JDialog { this.setTitle("Search for Servers"); this.setDefaultCloseOperation(DISPOSE_ON_CLOSE); - this.prevButton = new JButton("<"); - this.nextButton = new JButton(">"); - this.listModel = new PublicServerListModel(prevButton, nextButton); + this.listModel = new PublicServerListModel(); this.setContentPane(this.getContent(serverInfoListModel)); this.pack(); @@ -40,13 +36,22 @@ public class SearchServersDialog extends JDialog { panel.add(scrollPane, BorderLayout.CENTER); JPanel filtersPanel = new JPanel(new FlowLayout()); - JTextField searchField = new JTextField(20); + JTextField searchField = new JTextField(15); searchField.setToolTipText("Search for a server by name."); filtersPanel.add(searchField); + var prevButton = new JButton("<"); + var nextButton = new JButton(">"); + var refreshButton = new JButton("Refresh"); prevButton.addActionListener(e -> listModel.fetchPage(listModel.getCurrentPage() - 1)); filtersPanel.add(prevButton); nextButton.addActionListener(e -> listModel.fetchPage(listModel.getCurrentPage() + 1)); filtersPanel.add(nextButton); + refreshButton.addActionListener(e -> listModel.fetchPage(listModel.getCurrentPage())); + filtersPanel.add(refreshButton); + listModel.addListener(model -> { + prevButton.setEnabled(!model.isFirstPage()); + nextButton.setEnabled(!model.isLastPage()); + }); panel.add(filtersPanel, BorderLayout.NORTH);