From 6790591392ff9ca5a9272764eef636ba4bad10dd Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Sat, 3 Mar 2018 02:32:18 +0100 Subject: [PATCH 1/4] Add link browser utility service Add link browser utility service that will try to open specified link in browser, and in case operation fails displays message box and copy URL to clipboard. Signed-off-by: Tomas Slusny --- .../net/runelite/client/util/LinkBrowser.java | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java diff --git a/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java b/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java new file mode 100644 index 0000000000..0d0d8b7313 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2018, Tomas Slusny + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.util; + +import java.awt.Desktop; +import java.awt.Toolkit; +import java.awt.datatransfer.StringSelection; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; +import lombok.extern.slf4j.Slf4j; +import net.runelite.client.ui.ClientUI; + +/** + * Utility class used for browser navigation + */ +@Singleton +@Slf4j +public class LinkBrowser +{ + private final Provider clientUIProvider; + + @Inject + private LinkBrowser(final Provider clientUIProvider) + { + this.clientUIProvider = clientUIProvider; + } + + /** + * Tries to navigate to specified URL in browser. In case operation fails, displays message box with message + * and copies link to clipboard to navigate to. + * @param url url to open + * @return true if operation was successful + */ + public boolean browse(final String url) + { + if (!Desktop.isDesktopSupported()) + { + showMessageBox("Desktop is not supported. Press 'OK' and link will be copied to your clipboard.", url); + return false; + } + + final Desktop desktop = Desktop.getDesktop(); + + if (!desktop.isSupported(Desktop.Action.BROWSE)) + { + showMessageBox("Desktop browser is not supported. Press 'OK' and link will be copied to your clipboard.", url); + return false; + } + + try + { + desktop.browse(new URI(url)); + log.debug("Opened browser to {}", url); + return true; + } + catch (IOException | URISyntaxException ex) + { + log.warn("Unable to open URL {}. Error: {}", url, ex); + showMessageBox("Unable to open a URL. Press 'OK' and link will be copied to your clipboard.", url); + return false; + } + } + + /** + * Open swing message box with specified message and copy data to clipboard + * @param message message to show + */ + private void showMessageBox(final String message, final String data) + { + final ClientUI clientUI = clientUIProvider.get(); + + if (clientUI == null) + { + return; + } + + SwingUtilities.invokeLater(() -> + { + final int result = JOptionPane.showConfirmDialog(clientUI, message, "Message", + JOptionPane.OK_CANCEL_OPTION); + + if (result == JOptionPane.OK_OPTION) + { + final StringSelection stringSelection = new StringSelection(data); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(stringSelection, null); + } + }); + } +} From 3aa6a92aa34245a59c692e3a4c0457938e6495b5 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Sat, 3 Mar 2018 02:43:56 +0100 Subject: [PATCH 2/4] Use new LinkBrowser in SessionManager Use new LinkBrowser API in SessionManager for opening the links. Fixes: #434 Signed-off-by: Tomas Slusny --- .../client/account/SessionManager.java | 52 +++++-------------- 1 file changed, 14 insertions(+), 38 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java b/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java index f72fcf0b93..584583c5ca 100644 --- a/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java +++ b/runelite-client/src/main/java/net/runelite/client/account/SessionManager.java @@ -27,14 +27,11 @@ package net.runelite.client.account; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; import com.google.gson.Gson; -import java.awt.Desktop; import java.io.File; import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; -import java.net.URI; -import java.net.URISyntaxException; import java.time.Instant; import java.util.concurrent.ScheduledExecutorService; import javax.inject.Inject; @@ -45,6 +42,7 @@ import net.runelite.api.events.SessionClose; import net.runelite.api.events.SessionOpen; import net.runelite.client.RuneLite; import net.runelite.client.config.ConfigManager; +import net.runelite.client.util.LinkBrowser; import net.runelite.http.api.account.AccountClient; import net.runelite.http.api.account.OAuthResponse; import net.runelite.http.api.ws.messages.LoginResponse; @@ -60,19 +58,18 @@ public class SessionManager private AccountSession accountSession; private final EventBus eventBus; - - @Inject private ConfigManager configManager; - - @Inject private ScheduledExecutorService executor; - + private final LinkBrowser browser; private final AccountClient loginClient = new AccountClient(); @Inject - public SessionManager(EventBus eventBus) + public SessionManager(ConfigManager configManager, EventBus eventBus, ScheduledExecutorService executor, LinkBrowser browser) { + this.configManager = configManager; this.eventBus = eventBus; + this.executor = executor; + this.browser = browser; eventBus.register(this); } @@ -109,7 +106,7 @@ public class SessionManager openSession(session); } - public void saveSession() + private void saveSession() { if (accountSession == null) { @@ -128,7 +125,7 @@ public class SessionManager } } - public void deleteSession() + private void deleteSession() { SESSION_FILE.delete(); } @@ -137,9 +134,9 @@ public class SessionManager * Set the given session as the active session and open a socket to the * server with the given session * - * @param session + * @param session session */ - public void openSession(AccountSession session) + private void openSession(AccountSession session) { // If the ws session already exists, don't need to do anything if (wsclient == null || !wsclient.checkSession(session)) @@ -165,7 +162,7 @@ public class SessionManager eventBus.post(new SessionOpen()); } - public void closeSession() + private void closeSession() { if (wsclient != null) { @@ -200,7 +197,7 @@ public class SessionManager public void login() { - OAuthResponse login; + final OAuthResponse login; try { @@ -215,29 +212,8 @@ public class SessionManager // Create new session openSession(new AccountSession(login.getUid(), Instant.now())); - if (!Desktop.isDesktopSupported()) - { - log.info("Desktop is not supported. Visit {}", login.getOauthUrl()); - return; - } - - Desktop desktop = Desktop.getDesktop(); - if (!desktop.isSupported(Desktop.Action.BROWSE)) - { - log.info("Desktop browser is not supported. Visit {}", login.getOauthUrl()); - return; - } - - try - { - desktop.browse(new URI(login.getOauthUrl())); - - log.debug("Opened browser to {}", login.getOauthUrl()); - } - catch (IOException | URISyntaxException ex) - { - log.warn("Unable to open login page", ex); - } + // Navigate to login link + browser.browse(login.getOauthUrl()); } @Subscribe From 5bb29d32d5cc5cd0f39061d1670c38fb31c0d717 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Sun, 4 Mar 2018 17:35:38 +0100 Subject: [PATCH 3/4] Use new link browser in Grand Exchange plugin Use new link browser when opening links from search results of the Grand Exchange plugin Signed-off-by: Tomas Slusny --- .../grandexchange/GrandExchangeItemPanel.java | 41 +++++-------------- .../grandexchange/GrandExchangePanel.java | 5 ++- .../GrandExchangeSearchPanel.java | 8 +++- 3 files changed, 19 insertions(+), 35 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeItemPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeItemPanel.java index 3d1b13c2fb..b5c628761d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeItemPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeItemPanel.java @@ -26,14 +26,10 @@ package net.runelite.client.plugins.grandexchange; import java.awt.BorderLayout; import java.awt.Color; -import java.awt.Desktop; import java.awt.GridLayout; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; import java.text.NumberFormat; import javax.swing.ImageIcon; import javax.swing.JLabel; @@ -42,11 +38,13 @@ import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import javax.swing.border.LineBorder; import lombok.extern.slf4j.Slf4j; +import net.runelite.client.util.LinkBrowser; @Slf4j class GrandExchangeItemPanel extends JPanel { - GrandExchangeItemPanel(BufferedImage icon, String name, int itemID, int gePrice, Double haPrice) + GrandExchangeItemPanel(LinkBrowser linkBrowser, BufferedImage icon, String name, int itemID, int gePrice, Double + haPrice) { BorderLayout layout = new BorderLayout(); layout.setHgap(5); @@ -72,7 +70,7 @@ class GrandExchangeItemPanel extends JPanel @Override public void mouseReleased(MouseEvent e) { - geLink(name, itemID); + geLink(linkBrowser, name, itemID); } }); @@ -111,32 +109,13 @@ class GrandExchangeItemPanel extends JPanel add(rightPanel, BorderLayout.CENTER); } - public void geLink(String name, int itemID) + private void geLink(LinkBrowser linkBrowser, String name, int itemID) { - String url = "http://services.runescape.com/m=itemdb_oldschool/" + name.replaceAll(" ", "_") + "/viewitem?obj=" + itemID; + final String url = "http://services.runescape.com/m=itemdb_oldschool/" + + name.replaceAll(" ", "_") + + "/viewitem?obj=" + + itemID; - if (!Desktop.isDesktopSupported()) - { - log.info("Desktop is not supported. Visit {}", url); - return; - } - - Desktop desktop = Desktop.getDesktop(); - if (!desktop.isSupported(Desktop.Action.BROWSE)) - { - log.info("Desktop browser is not supported. Visit {}", url); - return; - } - - try - { - desktop.browse(new URI(url)); - - log.debug("Opened browser to {}", url); - } - catch (IOException | URISyntaxException ex) - { - log.warn("Unable to open grand exchange page", ex); - } + linkBrowser.browse(url); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePanel.java index 1c956029cf..b43e1e42b5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangePanel.java @@ -37,6 +37,7 @@ import net.runelite.api.Client; import net.runelite.api.GrandExchangeOffer; import net.runelite.client.game.ItemManager; import net.runelite.client.ui.PluginPanel; +import net.runelite.client.util.LinkBrowser; @Slf4j class GrandExchangePanel extends PluginPanel @@ -53,7 +54,7 @@ class GrandExchangePanel extends PluginPanel private JTabbedPane tabbedPane = new JTabbedPane(); @Inject - GrandExchangePanel(Client client, ItemManager itemManager, ScheduledExecutorService executor) + GrandExchangePanel(Client client, ItemManager itemManager, ScheduledExecutorService executor, LinkBrowser linkBrowser) { setLayout(new BorderLayout()); add(tabbedPane, BorderLayout.NORTH); @@ -67,7 +68,7 @@ class GrandExchangePanel extends PluginPanel } // Search Panel - searchPanel = new GrandExchangeSearchPanel(client, itemManager, executor); + searchPanel = new GrandExchangeSearchPanel(client, itemManager, executor, linkBrowser); tabbedPane.addTab("Offers", offerPanel); tabbedPane.addTab("Search", searchPanel); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeSearchPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeSearchPanel.java index 3a6ac59448..d452550a68 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeSearchPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeSearchPanel.java @@ -46,6 +46,7 @@ import net.runelite.api.Client; import net.runelite.api.ItemComposition; import net.runelite.client.game.ItemManager; import net.runelite.client.plugins.hiscore.IconTextField; +import net.runelite.client.util.LinkBrowser; import net.runelite.http.api.item.Item; import net.runelite.http.api.item.ItemClient; import net.runelite.http.api.item.ItemPrice; @@ -59,6 +60,7 @@ class GrandExchangeSearchPanel extends JPanel private final Client client; private final ItemManager itemManager; private final ScheduledExecutorService executor; + private final LinkBrowser linkBrowser; private ItemClient itemClient; @@ -69,11 +71,12 @@ class GrandExchangeSearchPanel extends JPanel private JPanel searchItemsPanel = new JPanel(); private JLabel searchingLabel = new JLabel("Searching..."); - GrandExchangeSearchPanel(Client client, ItemManager itemManager, ScheduledExecutorService executor) + GrandExchangeSearchPanel(Client client, ItemManager itemManager, ScheduledExecutorService executor, LinkBrowser linkBrowser) { this.client = client; this.itemManager = itemManager; this.executor = executor; + this.linkBrowser = linkBrowser; init(); } @@ -201,7 +204,8 @@ class GrandExchangeSearchPanel extends JPanel { for (GrandExchangeItems item : ITEMS_LIST) { - GrandExchangeItemPanel panel = new GrandExchangeItemPanel(item.getIcon(), item.getName(), item.getItemId(), item.getGePrice(), item.getHaPrice()); + GrandExchangeItemPanel panel = new GrandExchangeItemPanel(linkBrowser, item.getIcon(), item.getName(), + item.getItemId(), item.getGePrice(), item.getHaPrice()); searchItemsPanel.add(panel); } From 20f805cc1a0fc73b30cb256890ffc14bf4d1c345 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Sun, 4 Mar 2018 17:37:51 +0100 Subject: [PATCH 4/4] Use new link browser in feed plugin Use new link browser to open links from feed plugin entries. Signed-off-by: Tomas Slusny --- .../client/plugins/feed/FeedPanel.java | 26 ++++--------------- .../client/plugins/feed/FeedPlugin.java | 6 ++++- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/feed/FeedPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/feed/FeedPanel.java index 16472ec01d..1ef3400565 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/feed/FeedPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/feed/FeedPanel.java @@ -26,7 +26,6 @@ package net.runelite.client.plugins.feed; import java.awt.BorderLayout; import java.awt.Color; -import java.awt.Desktop; import java.awt.Dimension; import java.awt.Font; import java.awt.event.MouseAdapter; @@ -34,8 +33,6 @@ import java.awt.event.MouseEvent; import java.awt.font.FontRenderContext; import java.awt.image.BufferedImage; import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; import java.time.Duration; import java.time.Instant; import java.util.Comparator; @@ -52,6 +49,7 @@ import javax.swing.border.EmptyBorder; import lombok.extern.slf4j.Slf4j; import net.runelite.client.ui.FontManager; import net.runelite.client.ui.PluginPanel; +import net.runelite.client.util.LinkBrowser; import net.runelite.http.api.RuneLiteAPI; import net.runelite.http.api.feed.FeedItem; import net.runelite.http.api.feed.FeedItemType; @@ -116,11 +114,13 @@ class FeedPanel extends PluginPanel private final FeedConfig config; private final Supplier feedSupplier; + private final LinkBrowser linkBrowser; - FeedPanel(FeedConfig config, Supplier feedSupplier) + FeedPanel(FeedConfig config, Supplier feedSupplier, LinkBrowser linkBrowser) { this.config = config; this.feedSupplier = feedSupplier; + this.linkBrowser = linkBrowser; } void rebuildFeed() @@ -283,23 +283,7 @@ class FeedPanel extends PluginPanel public void mouseReleased(MouseEvent e) { avatarAndRight.setBackground(hoverColor); - - Desktop desktop = Desktop.getDesktop(); - - if (!desktop.isSupported(Desktop.Action.BROWSE)) - { - log.info("Desktop browser is not supported"); - return; - } - - try - { - desktop.browse(new URI(item.getUrl())); - } - catch (IOException | URISyntaxException ex) - { - log.warn("Unable to open URL " + item.getUrl(), ex); - } + linkBrowser.browse(item.getUrl()); } }); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/feed/FeedPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/feed/FeedPlugin.java index 714ba106cd..170c96ddc5 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/feed/FeedPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/feed/FeedPlugin.java @@ -42,6 +42,7 @@ import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.task.Schedule; import net.runelite.client.ui.ClientUI; import net.runelite.client.ui.NavigationButton; +import net.runelite.client.util.LinkBrowser; import net.runelite.http.api.feed.FeedClient; import net.runelite.http.api.feed.FeedResult; @@ -61,6 +62,9 @@ public class FeedPlugin extends Plugin @Inject private ScheduledExecutorService executorService; + @Inject + private LinkBrowser linkBrowser; + private FeedPanel feedPanel; private NavigationButton navButton; @@ -81,7 +85,7 @@ public class FeedPlugin extends Plugin @Override protected void startUp() throws Exception { - feedPanel = new FeedPanel(config, feedSupplier); + feedPanel = new FeedPanel(config, feedSupplier, linkBrowser); navButton = new NavigationButton( "News Feed",