Merge pull request #7410 from deathbeam/add-sync-now

Add button to sync local config with remote
This commit is contained in:
Tomas Slusny
2019-02-24 21:30:14 +00:00
committed by GitHub
3 changed files with 130 additions and 15 deletions

View File

@@ -43,8 +43,11 @@ import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.nio.channels.FileLock; import java.nio.channels.FileLock;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Instant; import java.time.Instant;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -70,6 +73,7 @@ import net.runelite.http.api.config.Configuration;
public class ConfigManager public class ConfigManager
{ {
private static final String SETTINGS_FILE_NAME = "settings.properties"; private static final String SETTINGS_FILE_NAME = "settings.properties";
private static final DateFormat TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
@Inject @Inject
EventBus eventBus; EventBus eventBus;
@@ -111,12 +115,17 @@ public class ConfigManager
load(); // load profile specific config load(); // load profile specific config
} }
private File getLocalPropertiesFile()
{
return new File(RuneLite.RUNELITE_DIR, SETTINGS_FILE_NAME);
}
private File getPropertiesFile() private File getPropertiesFile()
{ {
// Sessions that aren't logged in have no username // Sessions that aren't logged in have no username
if (session == null || session.getUsername() == null) if (session == null || session.getUsername() == null)
{ {
return new File(RuneLite.RUNELITE_DIR, SETTINGS_FILE_NAME); return getLocalPropertiesFile();
} }
else else
{ {
@@ -158,7 +167,13 @@ public class ConfigManager
for (ConfigEntry entry : configuration.getConfig()) for (ConfigEntry entry : configuration.getConfig())
{ {
log.debug("Loading configuration value from client {}: {}", entry.getKey(), entry.getValue()); log.debug("Loading configuration value from client {}: {}", entry.getKey(), entry.getValue());
final String[] split = entry.getKey().split("\\."); final String[] split = entry.getKey().split("\\.", 2);
if (split.length != 2)
{
continue;
}
final String groupName = split[0]; final String groupName = split[0];
final String key = split[1]; final String key = split[1];
final String value = entry.getValue(); final String value = entry.getValue();
@@ -174,7 +189,7 @@ public class ConfigManager
try try
{ {
saveToFile(); saveToFile(propertiesFile);
log.debug("Updated configuration on disk with the latest version"); log.debug("Updated configuration on disk with the latest version");
} }
@@ -184,6 +199,75 @@ public class ConfigManager
} }
} }
private synchronized void syncPropertiesFromFile(File propertiesFile)
{
final Properties properties = new Properties();
try (FileInputStream in = new FileInputStream(propertiesFile))
{
properties.load(new InputStreamReader(in, Charset.forName("UTF-8")));
}
catch (Exception e)
{
log.debug("Malformed properties, skipping update");
return;
}
final Map<String, String> copy = (Map) ImmutableMap.copyOf(this.properties);
copy.forEach((groupAndKey, value) ->
{
if (!properties.containsKey(groupAndKey))
{
final String[] split = groupAndKey.split("\\.", 2);
if (split.length != 2)
{
return;
}
final String groupName = split[0];
final String key = split[1];
unsetConfiguration(groupName, key);
}
});
properties.forEach((objGroupAndKey, objValue) ->
{
final String groupAndKey = String.valueOf(objGroupAndKey);
final String[] split = groupAndKey.split("\\.", 2);
if (split.length != 2)
{
return;
}
final String groupName = split[0];
final String key = split[1];
final String value = String.valueOf(objValue);
setConfiguration(groupName, key, value);
});
}
public void importLocal()
{
if (session == null)
{
// No session, no import
return;
}
final File file = new File(propertiesFile.getParent(), propertiesFile.getName() + "." + TIME_FORMAT.format(new Date()));
try
{
saveToFile(file);
}
catch (IOException e)
{
log.warn("Backup failed, skipping import", e);
return;
}
syncPropertiesFromFile(getLocalPropertiesFile());
}
private synchronized void loadFromFile() private synchronized void loadFromFile()
{ {
properties.clear(); properties.clear();
@@ -231,7 +315,7 @@ public class ConfigManager
} }
} }
private synchronized void saveToFile() throws IOException private synchronized void saveToFile(final File propertiesFile) throws IOException
{ {
propertiesFile.getParentFile().mkdirs(); propertiesFile.getParentFile().mkdirs();
@@ -294,8 +378,6 @@ public class ConfigManager
public void setConfiguration(String groupName, String key, String value) public void setConfiguration(String groupName, String key, String value)
{ {
log.debug("Setting configuration value for {}.{} to {}", groupName, key, value);
String oldValue = (String) properties.setProperty(groupName + "." + key, value); String oldValue = (String) properties.setProperty(groupName + "." + key, value);
if (Objects.equals(oldValue, value)) if (Objects.equals(oldValue, value))
@@ -303,6 +385,8 @@ public class ConfigManager
return; return;
} }
log.debug("Setting configuration value for {}.{} to {}", groupName, key, value);
synchronized (pendingChanges) synchronized (pendingChanges)
{ {
pendingChanges.put(groupName + "." + key, value); pendingChanges.put(groupName + "." + key, value);
@@ -312,7 +396,7 @@ public class ConfigManager
{ {
try try
{ {
saveToFile(); saveToFile(propertiesFile);
} }
catch (IOException ex) catch (IOException ex)
{ {
@@ -337,8 +421,6 @@ public class ConfigManager
public void unsetConfiguration(String groupName, String key) public void unsetConfiguration(String groupName, String key)
{ {
log.debug("Unsetting configuration value for {}.{}", groupName, key);
String oldValue = (String) properties.remove(groupName + "." + key); String oldValue = (String) properties.remove(groupName + "." + key);
if (oldValue == null) if (oldValue == null)
@@ -346,6 +428,8 @@ public class ConfigManager
return; return;
} }
log.debug("Unsetting configuration value for {}.{}", groupName, key);
synchronized (pendingChanges) synchronized (pendingChanges)
{ {
pendingChanges.put(groupName + "." + key, null); pendingChanges.put(groupName + "." + key, null);
@@ -355,7 +439,7 @@ public class ConfigManager
{ {
try try
{ {
saveToFile(); saveToFile(propertiesFile);
} }
catch (IOException ex) catch (IOException ex)
{ {

View File

@@ -40,6 +40,7 @@ import javax.inject.Singleton;
import javax.swing.Box; import javax.swing.Box;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.border.EmptyBorder; import javax.swing.border.EmptyBorder;
import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkEvent;
@@ -48,6 +49,7 @@ import net.runelite.api.events.SessionClose;
import net.runelite.api.events.SessionOpen; import net.runelite.api.events.SessionOpen;
import net.runelite.client.RuneLiteProperties; import net.runelite.client.RuneLiteProperties;
import net.runelite.client.account.SessionManager; import net.runelite.client.account.SessionManager;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.EventBus;
import net.runelite.client.eventbus.Subscribe; import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.ui.ColorScheme; import net.runelite.client.ui.ColorScheme;
@@ -66,9 +68,12 @@ public class InfoPanel extends PluginPanel
private static final ImageIcon DISCORD_ICON; private static final ImageIcon DISCORD_ICON;
private static final ImageIcon PATREON_ICON; private static final ImageIcon PATREON_ICON;
private static final ImageIcon WIKI_ICON; private static final ImageIcon WIKI_ICON;
private static final ImageIcon IMPORT_ICON;
private final JLabel loggedLabel = new JLabel(); private final JLabel loggedLabel = new JLabel();
private final JRichTextPane emailLabel = new JRichTextPane(); private final JRichTextPane emailLabel = new JRichTextPane();
private JPanel syncPanel;
private JPanel actionsContainer;
@Inject @Inject
@Nullable @Nullable
@@ -86,6 +91,9 @@ public class InfoPanel extends PluginPanel
@Inject @Inject
private ScheduledExecutorService executor; private ScheduledExecutorService executor;
@Inject
private ConfigManager configManager;
static static
{ {
ARROW_RIGHT_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "/util/arrow_right.png")); ARROW_RIGHT_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "/util/arrow_right.png"));
@@ -93,6 +101,7 @@ public class InfoPanel extends PluginPanel
DISCORD_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "discord_icon.png")); DISCORD_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "discord_icon.png"));
PATREON_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "patreon_icon.png")); PATREON_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "patreon_icon.png"));
WIKI_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "wiki_icon.png")); WIKI_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "wiki_icon.png"));
IMPORT_ICON = new ImageIcon(ImageUtil.getResourceStreamFromClass(InfoPanel.class, "import_icon.png"));
} }
void init() void init()
@@ -150,11 +159,22 @@ public class InfoPanel extends PluginPanel
versionPanel.add(loggedLabel); versionPanel.add(loggedLabel);
versionPanel.add(emailLabel); versionPanel.add(emailLabel);
updateLoggedIn(); actionsContainer = new JPanel();
JPanel actionsContainer = new JPanel();
actionsContainer.setBorder(new EmptyBorder(10, 0, 0, 0)); actionsContainer.setBorder(new EmptyBorder(10, 0, 0, 0));
actionsContainer.setLayout(new GridLayout(4, 1, 0, 10)); actionsContainer.setLayout(new GridLayout(0, 1, 0, 10));
syncPanel = buildLinkPanel(IMPORT_ICON, "Import local settings", "to remote RuneLite account", () ->
{
final int result = JOptionPane.showOptionDialog(syncPanel,
"This will replace your current RuneLite account settings with settings from your local profile.",
"Are you sure?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE,
null, new String[]{"Yes", "No"}, "No");
if (result == JOptionPane.YES_OPTION)
{
configManager.importLocal();
}
});
actionsContainer.add(buildLinkPanel(GITHUB_ICON, "Report an issue or", "make a suggestion", runeLiteProperties.getGithubLink())); actionsContainer.add(buildLinkPanel(GITHUB_ICON, "Report an issue or", "make a suggestion", runeLiteProperties.getGithubLink()));
actionsContainer.add(buildLinkPanel(DISCORD_ICON, "Talk to us on our", "discord server", runeLiteProperties.getDiscordInvite())); actionsContainer.add(buildLinkPanel(DISCORD_ICON, "Talk to us on our", "discord server", runeLiteProperties.getDiscordInvite()));
@@ -164,6 +184,7 @@ public class InfoPanel extends PluginPanel
add(versionPanel, BorderLayout.NORTH); add(versionPanel, BorderLayout.NORTH);
add(actionsContainer, BorderLayout.CENTER); add(actionsContainer, BorderLayout.CENTER);
updateLoggedIn();
eventBus.register(this); eventBus.register(this);
} }
@@ -171,6 +192,14 @@ public class InfoPanel extends PluginPanel
* Builds a link panel with a given icon, text and url to redirect to. * Builds a link panel with a given icon, text and url to redirect to.
*/ */
private static JPanel buildLinkPanel(ImageIcon icon, String topText, String bottomText, String url) private static JPanel buildLinkPanel(ImageIcon icon, String topText, String bottomText, String url)
{
return buildLinkPanel(icon, topText, bottomText, () -> LinkBrowser.browse(url));
}
/**
* Builds a link panel with a given icon, text and callable to call.
*/
private static JPanel buildLinkPanel(ImageIcon icon, String topText, String bottomText, Runnable callback)
{ {
JPanel container = new JPanel(); JPanel container = new JPanel();
container.setBackground(ColorScheme.DARKER_GRAY_COLOR); container.setBackground(ColorScheme.DARKER_GRAY_COLOR);
@@ -193,7 +222,6 @@ public class InfoPanel extends PluginPanel
@Override @Override
public void mousePressed(MouseEvent mouseEvent) public void mousePressed(MouseEvent mouseEvent)
{ {
LinkBrowser.browse(url);
container.setBackground(pressedColor); container.setBackground(pressedColor);
textContainer.setBackground(pressedColor); textContainer.setBackground(pressedColor);
} }
@@ -201,6 +229,7 @@ public class InfoPanel extends PluginPanel
@Override @Override
public void mouseReleased(MouseEvent e) public void mouseReleased(MouseEvent e)
{ {
callback.run();
container.setBackground(hoverColor); container.setBackground(hoverColor);
textContainer.setBackground(hoverColor); textContainer.setBackground(hoverColor);
} }
@@ -252,12 +281,14 @@ public class InfoPanel extends PluginPanel
emailLabel.setContentType("text/plain"); emailLabel.setContentType("text/plain");
emailLabel.setText(name); emailLabel.setText(name);
loggedLabel.setText("Logged in as"); loggedLabel.setText("Logged in as");
actionsContainer.add(syncPanel, 0);
} }
else else
{ {
emailLabel.setContentType("text/html"); emailLabel.setContentType("text/html");
emailLabel.setText("<a href=\"" + RUNELITE_LOGIN + "\">Login</a> to sync settings to the cloud."); emailLabel.setText("<a href=\"" + RUNELITE_LOGIN + "\">Login</a> to sync settings to the cloud.");
loggedLabel.setText("Not logged in"); loggedLabel.setText("Not logged in");
actionsContainer.remove(syncPanel);
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB