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 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", 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); } 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); + } + }); + } +}