Merge pull request #478 from Abextm/info-panel

Add info panel
This commit is contained in:
Adam
2018-02-03 22:48:03 -05:00
committed by GitHub
8 changed files with 443 additions and 94 deletions

View File

@@ -38,6 +38,7 @@ public class RuneLiteProperties
{
private static final String RUNELITE_TITLE = "runelite.title";
private static final String RUNELITE_VERSION = "runelite.version";
private static final String RUNESCAPE_VERSION = "runescape.version";
private final Properties properties = new Properties();
@@ -64,4 +65,9 @@ public class RuneLiteProperties
{
return properties.getProperty(RUNELITE_VERSION);
}
public String getRunescapeVersion()
{
return properties.getProperty(RUNESCAPE_VERSION);
}
}

View File

@@ -25,12 +25,17 @@
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;
import javax.inject.Singleton;
@@ -41,6 +46,8 @@ import net.runelite.client.config.ConfigManager;
import net.runelite.api.events.SessionClose;
import net.runelite.api.events.SessionOpen;
import net.runelite.http.api.account.AccountClient;
import net.runelite.http.api.account.OAuthResponse;
import net.runelite.http.api.ws.messages.LoginResponse;
@Singleton
@Slf4j
@@ -52,8 +59,7 @@ public class SessionManager
@Getter
private AccountSession accountSession;
@Inject
private EventBus eventBus;
private final EventBus eventBus;
@Inject
private ConfigManager configManager;
@@ -61,6 +67,15 @@ public class SessionManager
@Inject
private ScheduledExecutorService executor;
private final AccountClient loginClient = new AccountClient();
@Inject
public SessionManager(EventBus eventBus)
{
this.eventBus = eventBus;
eventBus.register(this);
}
public void loadSession()
{
if (!SESSION_FILE.exists())
@@ -165,6 +180,16 @@ public class SessionManager
log.debug("Logging out of account {}", accountSession.getUsername());
AccountClient client = new AccountClient(accountSession.getUuid());
try
{
client.logout();
}
catch (IOException ex)
{
log.warn("Unable to logout of session", ex);
}
accountSession = null; // No more account
// Restore config
@@ -172,4 +197,68 @@ public class SessionManager
eventBus.post(new SessionClose());
}
public void login()
{
OAuthResponse login;
try
{
login = loginClient.login();
}
catch (IOException ex)
{
log.warn("Unable to get oauth url", ex);
return;
}
// 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);
}
}
@Subscribe
public void onLogin(LoginResponse loginResponse)
{
log.debug("Now logged in as {}", loginResponse.getUsername());
AccountSession session = getAccountSession();
session.setUsername(loginResponse.getUsername());
// Open session, again, now that we have a username
// This triggers onSessionOpen
openSession(session);
// Save session to disk
saveSession();
}
public void logout()
{
closeSession();
deleteSession();
}
}

View File

@@ -25,16 +25,12 @@
package net.runelite.client.plugins.account;
import com.google.common.eventbus.Subscribe;
import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.time.Instant;
import java.util.concurrent.ScheduledExecutorService;
import javax.imageio.ImageIO;
import javax.inject.Inject;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.events.SessionClose;
import net.runelite.client.account.AccountSession;
import net.runelite.client.account.SessionManager;
import net.runelite.api.events.SessionOpen;
@@ -44,9 +40,6 @@ import net.runelite.client.ui.ClientUI;
import net.runelite.client.ui.NavigationButton;
import net.runelite.client.ui.PluginToolbar;
import net.runelite.client.util.RunnableExceptionLogger;
import net.runelite.http.api.account.AccountClient;
import net.runelite.http.api.account.OAuthResponse;
import net.runelite.http.api.ws.messages.LoginResponse;
@PluginDescriptor(
name = "Account plugin",
@@ -67,8 +60,6 @@ public class AccountPlugin extends Plugin
private NavigationButton loginButton;
private NavigationButton logoutButton;
private final AccountClient loginClient = new AccountClient();
@Override
protected void startUp() throws Exception
{
@@ -88,91 +79,22 @@ public class AccountPlugin extends Plugin
private void loginClick(ActionEvent ae)
{
executor.execute(RunnableExceptionLogger.wrap(this::openLoginPage));
executor.execute(RunnableExceptionLogger.wrap(sessionManager::login));
}
private void logoutClick(ActionEvent ae)
{
// Destroy session
AccountSession session = sessionManager.getAccountSession();
if (session != null)
{
AccountClient client = new AccountClient(session.getUuid());
try
{
client.logout();
}
catch (IOException ex)
{
log.warn("Unable to logout of session", ex);
}
}
sessionManager.closeSession(); // remove session from client
sessionManager.deleteSession(); // delete saved session file
sessionManager.logout();
}
@Subscribe
public void onSessionClose(SessionClose e)
{
// Replace logout nav button with login
PluginToolbar navigationPanel = ui.getPluginToolbar();
navigationPanel.removeNavigation(logoutButton);
navigationPanel.addNavigation(loginButton);
}
private void openLoginPage()
{
OAuthResponse login;
try
{
login = loginClient.login();
}
catch (IOException ex)
{
log.warn("Unable to get oauth url", ex);
return;
}
// Create new session
sessionManager.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);
}
}
@Subscribe
public void onLogin(LoginResponse loginResponse)
{
log.debug("Now logged in as {}", loginResponse.getUsername());
AccountSession session = sessionManager.getAccountSession();
session.setUsername(loginResponse.getUsername());
// Open session, again, now that we have a username
// This triggers onSessionOpen
sessionManager.openSession(session);
// Save session to disk
sessionManager.saveSession();
navigationPanel.repaint();
}
@Subscribe
@@ -187,15 +109,11 @@ public class AccountPlugin extends Plugin
log.debug("Session opened as {}", session.getUsername());
replaceLoginWithLogout();
}
private void replaceLoginWithLogout()
{
// Replace login nav button with logout
PluginToolbar navigationPanel = ui.getPluginToolbar();
navigationPanel.removeNavigation(loginButton);
navigationPanel.addNavigation(logoutButton);
navigationPanel.repaint();
}
}

View File

@@ -0,0 +1,173 @@
/*
* Copyright (c) 2018 Abex
* 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.plugins.info;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import java.awt.Font;
import com.google.inject.Inject;
import java.util.concurrent.ScheduledExecutorService;
import javax.annotation.Nullable;
import javax.swing.GroupLayout;
import javax.swing.JLabel;
import javax.swing.LayoutStyle;
import javax.swing.event.HyperlinkEvent;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.events.SessionClose;
import net.runelite.api.events.SessionOpen;
import net.runelite.client.RuneLiteProperties;
import net.runelite.client.account.SessionManager;
import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.PluginPanel;
import net.runelite.client.util.RunnableExceptionLogger;
@Slf4j
public class InfoPanel extends PluginPanel
{
private final static String RUNELITE_LOGIN = "https://runelite_login/";
@Inject
@Nullable
private Client client;
@Inject
private RuneLiteProperties runeLiteProperties;
@Inject
private EventBus eventBus;
@Inject
private SessionManager sessionManager;
@Inject
private ScheduledExecutorService executor;
private final GroupLayout layout = new GroupLayout(this);
private final JLabel usernameHeader = new JLabel();
private final JRichTextPane username = new JRichTextPane();
void init()
{
setLayout(layout);
final Font smallFont = FontManager.getRunescapeSmallFont();
final JLabel runeliteVersionHeader = new JLabel("RuneLite version");
runeliteVersionHeader.setFont(smallFont);
final JLabel runeliteVersion = new JLabel(runeLiteProperties.getVersion());
final JLabel runescapeVersionHeader = new JLabel("OldSchool Engine");
runescapeVersionHeader.setFont(smallFont);
String engineVer = "Unknown";
if (client != null)
{
engineVer = String.format("Rev %s", runeLiteProperties.getRunescapeVersion());
}
final JLabel runescapeVersion = new JLabel(engineVer);
usernameHeader.setFont(smallFont);
username.enableAutoLinkHandler(false);
username.addHyperlinkListener(e ->
{
if (HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType()) && e.getURL() != null)
{
if (e.getURL().toString().equals(RUNELITE_LOGIN))
{
executor.execute(RunnableExceptionLogger.wrap(sessionManager::login));
}
}
});
setNotLoggedIn();
final JRichTextPane issueLink = new JRichTextPane("text/html",
"RuneLite is open source!<br>"
+ "Found an issue? Want a feature?<br>"
+ "<a href=\"https://github.com/runelite/runelite/issues\">"
+ "Open an issue on GitHub!"
+ "</a>"
);
layout.setVerticalGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup()
.addComponent(runeliteVersionHeader)
.addComponent(runescapeVersionHeader)
).addGroup(layout.createParallelGroup()
.addComponent(runeliteVersion)
.addComponent(runescapeVersion)
).addGap(6)
.addComponent(usernameHeader)
.addGroup(layout.createParallelGroup()
.addComponent(username)
)
.addGap(12)
.addComponent(issueLink)
);
layout.setHorizontalGroup(layout.createParallelGroup()
.addGroup(layout.createSequentialGroup()
.addComponent(runeliteVersionHeader)
.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)
.addComponent(runescapeVersionHeader)
).addGroup(layout.createSequentialGroup()
.addComponent(runeliteVersion)
.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)
.addComponent(runescapeVersion)
)
.addComponent(usernameHeader)
.addComponent(username)
.addComponent(issueLink)
);
eventBus.register(this);
}
private void setNotLoggedIn()
{
username.setContentType("text/html");
username.setText("<a href=\"" + RUNELITE_LOGIN + "\">Login</a> to sync settings to the cloud.");
usernameHeader.setText("Not logged in");
}
@Subscribe
private void onSessionOpen(SessionOpen sessionOpen)
{
String name = sessionManager.getAccountSession().getUsername();
if (name != null)
{
username.setContentType("text/plain");
username.setText(name);
usernameHeader.setText("Logged in as");
}
}
@Subscribe
private void onSessionClose(SessionClose e)
{
setNotLoggedIn();
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 2018 Abex
* 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.plugins.info;
import com.google.inject.Binder;
import javax.imageio.ImageIO;
import javax.inject.Inject;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.ClientUI;
import net.runelite.client.ui.NavigationButton;
@PluginDescriptor(
name = "Info panel plugin",
loadWhenOutdated = true
)
public class InfoPlugin extends Plugin
{
@Inject
private ClientUI ui;
@Override
public void configure(Binder binder)
{
binder.bind(InfoPanel.class);
}
@Override
protected void startUp() throws Exception
{
final InfoPanel panel = injector.getInstance(InfoPanel.class);
panel.init();
final NavigationButton navButton = new NavigationButton(
"Info",
ImageIO.read(getClass().getResourceAsStream("info_icon.png")),
() -> panel
);
ui.getPluginToolbar().addNavigation(navButton);
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (c) 2018 Abex
* 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.plugins.info;
import java.awt.Desktop;
import java.io.IOException;
import java.net.URISyntaxException;
import javax.swing.BorderFactory;
import javax.swing.JEditorPane;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.html.HTMLEditorKit;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class JRichTextPane extends JEditorPane
{
private HyperlinkListener linkHandler;
public JRichTextPane()
{
super();
setHighlighter(null);
setEditable(false);
setOpaque(false);
enableAutoLinkHandler(true);
setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
HTMLEditorKit ek = (HTMLEditorKit) getEditorKitForContentType("text/html");
ek.getStyleSheet().addRule("a {color: #DDDDDD }");
}
public JRichTextPane(String type, String text)
{
this();
setContentType(type);
setText(text);
}
public void enableAutoLinkHandler(boolean enable)
{
if (enable != (linkHandler != null))
{
if (enable)
{
linkHandler = e ->
{
log.info(e.toString());
if (HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType()) && e.getURL() != null)
{
if (Desktop.isDesktopSupported())
{
try
{
Desktop.getDesktop().browse(e.getURL().toURI());
}
catch (URISyntaxException | IOException ex)
{
log.info("Error opening link", ex);
}
}
}
};
addHyperlinkListener(linkHandler);
}
else
{
removeHyperlinkListener(linkHandler);
linkHandler = null;
}
}
}
public boolean getAutoLinkHandlerEnabled()
{
return linkHandler != null;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,3 +1,3 @@
runelite.title=RuneLite
runelite.version=${project.version}
runescape.version=${rs.version}