From c1d5e3ae161b6c195f37306a5c67e8eef4904562 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 16 Mar 2020 19:52:15 -0400 Subject: [PATCH] hiscore panel: autocomplete recent search history Co-authored-by: Daniel --- .../client/plugins/hiscore/HiscorePanel.java | 13 ++++- .../client/plugins/hiscore/HiscorePlugin.java | 23 +-------- .../plugins/hiscore/NameAutocompleter.java | 48 +++++++++++++++---- .../plugins/hiscore/HiscorePanelTest.java | 5 +- 4 files changed, 54 insertions(+), 35 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePanel.java index 4e67a0868c..ca5df48a6b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePanel.java @@ -121,6 +121,7 @@ public class HiscorePanel extends PluginPanel private Client client; private final HiscoreConfig config; + private final NameAutocompleter nameAutocompleter; private final IconTextField searchBar; @@ -141,10 +142,11 @@ public class HiscorePanel extends PluginPanel private boolean loading = false; @Inject - public HiscorePanel(HiscoreConfig config) + public HiscorePanel(HiscoreConfig config, NameAutocompleter nameAutocompleter) { super(); this.config = config; + this.nameAutocompleter = nameAutocompleter; // The layout seems to be ignoring the top margin and only gives it // a 2-3 pixel margin, so I set the value to 18 to compensate @@ -295,6 +297,13 @@ public class HiscorePanel extends PluginPanel add(bossPanel, c); c.gridy++; + + addInputKeyListener(nameAutocompleter); + } + + void shutdown() + { + removeInputKeyListener(nameAutocompleter); } @Override @@ -418,6 +427,8 @@ public class HiscorePanel extends PluginPanel searchBar.setEditable(true); loading = false; + nameAutocompleter.addToSearchHistory(result.getPlayer().toLowerCase()); + for (Map.Entry entry : skillLabels.entrySet()) { HiscoreSkill skill = entry.getKey(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePlugin.java index d2320484db..5ce1d4b9e9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePlugin.java @@ -41,12 +41,12 @@ import net.runelite.api.Client; import net.runelite.api.MenuAction; import net.runelite.api.MenuEntry; import net.runelite.api.events.ChatMessage; -import net.runelite.client.events.ConfigChanged; import net.runelite.api.events.MenuEntryAdded; import net.runelite.api.events.PlayerMenuOptionClicked; import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.ConfigChanged; import net.runelite.client.menus.MenuManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @@ -88,9 +88,6 @@ public class HiscorePlugin extends Plugin private NavigationButton navButton; private HiscorePanel hiscorePanel; - @Inject - private NameAutocompleter autocompleter; - @Provides HiscoreConfig provideConfig(ConfigManager configManager) { @@ -117,16 +114,12 @@ public class HiscorePlugin extends Plugin { menuManager.get().addPlayerMenuItem(LOOKUP); } - if (config.autocomplete()) - { - hiscorePanel.addInputKeyListener(autocompleter); - } } @Override protected void shutDown() throws Exception { - hiscorePanel.removeInputKeyListener(autocompleter); + hiscorePanel.shutdown(); clientToolbar.removeNavigation(navButton); if (client != null) @@ -149,18 +142,6 @@ public class HiscorePlugin extends Plugin menuManager.get().addPlayerMenuItem(LOOKUP); } } - - if (event.getKey().equals("autocomplete")) - { - if (config.autocomplete()) - { - hiscorePanel.addInputKeyListener(autocompleter); - } - else - { - hiscorePanel.removeInputKeyListener(autocompleter); - } - } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/NameAutocompleter.java b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/NameAutocompleter.java index e89cbb2a8d..1cdbaf526e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/NameAutocompleter.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/NameAutocompleter.java @@ -24,6 +24,7 @@ */ package net.runelite.client.plugins.hiscore; +import com.google.common.collect.EvictingQueue; import com.google.inject.Inject; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; @@ -32,10 +33,12 @@ import java.util.Objects; import java.util.Optional; import java.util.regex.Pattern; import javax.annotation.Nullable; +import javax.inject.Singleton; import javax.swing.SwingUtilities; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import javax.swing.text.JTextComponent; +import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import net.runelite.api.ClanMemberManager; import net.runelite.api.Client; @@ -45,6 +48,7 @@ import net.runelite.api.NameableContainer; import net.runelite.api.Player; @Slf4j +@Singleton class NameAutocompleter implements KeyListener { /** @@ -57,7 +61,12 @@ class NameAutocompleter implements KeyListener */ private static final Pattern INVALID_CHARS = Pattern.compile("[^a-zA-Z0-9_ -]"); + private static final int MAX_SEARCH_HISTORY = 25; + private final Client client; + private final HiscoreConfig hiscoreConfig; + + private final EvictingQueue searchHistory = EvictingQueue.create(MAX_SEARCH_HISTORY); /** * The name currently being autocompleted. @@ -70,9 +79,10 @@ class NameAutocompleter implements KeyListener private Pattern autocompleteNamePattern; @Inject - private NameAutocompleter(@Nullable Client client) + private NameAutocompleter(@Nullable Client client, HiscoreConfig hiscoreConfig) { this.client = client; + this.hiscoreConfig = hiscoreConfig; } @Override @@ -90,6 +100,11 @@ class NameAutocompleter implements KeyListener @Override public void keyTyped(KeyEvent e) { + if (!hiscoreConfig.autocomplete()) + { + return; + } + final JTextComponent input = (JTextComponent)e.getSource(); final String inputText = input.getText(); @@ -189,17 +204,22 @@ class NameAutocompleter implements KeyListener return false; } - autocompleteName = Optional.empty(); + // Search all previous successful queries + autocompleteName = searchHistory.stream() + .filter(n -> pattern.matcher(n).matches()) + .findFirst(); - // TODO: Search lookup history - - NameableContainer friendContainer = client.getFriendContainer(); - if (friendContainer != null) + // Search friends if previous searches weren't matched + if (!autocompleteName.isPresent()) { - autocompleteName = Arrays.stream(friendContainer.getMembers()) - .map(Nameable::getName) - .filter(n -> pattern.matcher(n).matches()) - .findFirst(); + NameableContainer friendContainer = client.getFriendContainer(); + if (friendContainer != null) + { + autocompleteName = Arrays.stream(friendContainer.getMembers()) + .map(Nameable::getName) + .filter(n -> pattern.matcher(n).matches()) + .findFirst(); + } } // Search clan if a friend wasn't found @@ -241,6 +261,14 @@ class NameAutocompleter implements KeyListener return autocompleteName.isPresent(); } + void addToSearchHistory(@NonNull String name) + { + if (!searchHistory.contains(name)) + { + searchHistory.offer(name); + } + } + private boolean isExpectedNext(JTextComponent input, String nextChar) { String expected; diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/hiscore/HiscorePanelTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/hiscore/HiscorePanelTest.java index 3d5255f088..dfee0deeba 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/hiscore/HiscorePanelTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/hiscore/HiscorePanelTest.java @@ -27,15 +27,14 @@ package net.runelite.client.plugins.hiscore; import static net.runelite.client.plugins.hiscore.HiscorePanel.formatLevel; import static org.junit.Assert.assertEquals; import org.junit.Test; +import static org.mockito.Mockito.mock; public class HiscorePanelTest { @Test public void testConstructor() { - new HiscorePanel(new HiscoreConfig() - { - }); + new HiscorePanel(mock(HiscoreConfig.class), mock(NameAutocompleter.class)); } @Test