浏览代码

Filtering is now separate from sorting.
You can select a filter and then sort.
Selecting the same filter twice disables it.
Selecting the sort button twice inverts it.

Stephen Damm 6 年之前
父节点
当前提交
e45b3ec341

+ 13 - 5
SongBrowserPlugin/DataAccess/SongBrowserSettings.cs

@@ -12,12 +12,23 @@ namespace SongBrowserPlugin.DataAccess
     {
         Default,
         Author,
-        Favorites,
         Original,
         Newest,        
         PlayCount,
         Difficulty,
         Random,
+
+        // Deprecated
+        Favorites,
+        Playlist,
+        Search
+    }
+
+    [Serializable]
+    public enum SongFilterMode
+    {
+        None,
+        Favorites,
         Playlist,
         Search
     }
@@ -26,6 +37,7 @@ namespace SongBrowserPlugin.DataAccess
     public class SongBrowserSettings
     {
         public SongSortMode sortMode = default(SongSortMode);
+        public SongFilterMode filterMode = default(SongFilterMode);
 
         // Deprecated        
         private List<String> _oldFavorites = default(List<String>);
@@ -46,10 +58,6 @@ namespace SongBrowserPlugin.DataAccess
         [XmlIgnore]
         private HashSet<String> _favorites;
 
-        [NonSerialized]
-        [XmlIgnore]
-        private int _lastFavoritesCount = 0;
-
         [XmlArray(@"favorites")]
         public List<String> OldFavorites
         {

+ 89 - 80
SongBrowserPlugin/SongBrowserModel.cs

@@ -85,6 +85,7 @@ namespace SongBrowserPlugin
         private SongBrowserSettings _settings;
 
         // song list management
+        private List<StandardLevelSO> _filteredSongs;
         private List<StandardLevelSO> _sortedSongs;
         private List<StandardLevelSO> _originalSongs;
         private Dictionary<String, SongLoaderPlugin.OverrideClasses.CustomLevel> _levelIdToCustomLevel;
@@ -482,52 +483,70 @@ namespace SongBrowserPlugin
                     _log.Debug("Missing KEY: {0}", level.levelID);
                 }
             }*/
-            
-            Stopwatch stopwatch = Stopwatch.StartNew();           
 
-            List<StandardLevelSO> songList = null;
-            if (this._settings.sortMode == SongSortMode.Playlist && this.CurrentPlaylist != null)
-            {                
-                songList = null;
+            // Playlist filter will load the original songs.
+            if (this._settings.filterMode == SongFilterMode.Playlist && this.CurrentPlaylist != null)
+            {
+                _originalSongs = null;
             }
             else
             {
                 _log.Debug("Showing songs for directory: {0}", _directoryStack.Peek().Key);
-                songList = _directoryStack.Peek().Levels;
+                _originalSongs = _directoryStack.Peek().Levels;
             }
-            
-            switch (_settings.sortMode)
+
+            // filter
+            _log.Debug("Starting filtering songs...");
+            Stopwatch stopwatch = Stopwatch.StartNew();
+
+            switch (_settings.filterMode)
             {
-                case SongSortMode.Favorites:
-                    SortFavorites(songList);
+                case SongFilterMode.Favorites:
+                    FilterFavorites(_originalSongs);
+                    break;
+                case SongFilterMode.Search:
+                    FilterSearch(_originalSongs);
                     break;
+                case SongFilterMode.Playlist:
+                    FilterPlaylist();
+                    break;
+                case SongFilterMode.None:
+                default:
+                    _log.Info("No song filter selected...");
+                    _filteredSongs = _originalSongs;
+                    break;
+            }
+
+            stopwatch.Stop();
+            _log.Info("Filtering songs took {0}ms", stopwatch.ElapsedMilliseconds);
+
+            // sort
+            _log.Debug("Starting to sort songs...");
+            stopwatch = Stopwatch.StartNew();
+
+            switch (_settings.sortMode)
+            {
                 case SongSortMode.Original:
-                    SortOriginal(songList);
+                    SortOriginal(_filteredSongs);
                     break;
                 case SongSortMode.Newest:
-                    SortNewest(songList);
+                    SortNewest(_filteredSongs);
                     break;
                 case SongSortMode.Author:
-                    SortAuthor(songList);
+                    SortAuthor(_filteredSongs);
                     break;
                 case SongSortMode.PlayCount:
-                    SortPlayCount(songList, _currentGamePlayMode);
+                    SortPlayCount(_filteredSongs, _currentGamePlayMode);
                     break;
                 case SongSortMode.Difficulty:
-                    SortDifficulty(songList);
+                    SortDifficulty(_filteredSongs);
                     break;
                 case SongSortMode.Random:
-                    SortRandom(songList);
-                    break;
-                case SongSortMode.Search:
-                    SortSearch(songList);
-                    break;
-                case SongSortMode.Playlist:
-                    SortPlaylist();
+                    SortRandom(_filteredSongs);
                     break;
                 case SongSortMode.Default:
                 default:
-                    SortSongName(songList);
+                    SortSongName(_filteredSongs);
                     break;
             }
 
@@ -540,30 +559,62 @@ namespace SongBrowserPlugin
             _log.Info("Sorting songs took {0}ms", stopwatch.ElapsedMilliseconds);
         }    
         
-        private void SortFavorites(List<StandardLevelSO> levels)
+        private void FilterFavorites(List<StandardLevelSO> levels)
         {
-            _log.Info("Sorting song list as favorites");
-            /*_sortedSongs = levels
-                .AsQueryable()
-                .OrderBy(x => _settings.Favorites.Contains(x.levelID) == false)
-                .ThenBy(x => x.songName)
-                .ThenBy(x => x.songAuthorName)
-                .ToList();*/
-            _sortedSongs = levels
-                .AsQueryable()
+            _log.Info("Filtering song list as favorites");
+            _filteredSongs = levels
                 .Where(x => _settings.Favorites.Contains(x.levelID))
-                .OrderBy(x => x.songName)
+                .ToList();
+        }
+
+        private void FilterSearch(List<StandardLevelSO> levels)
+        {
+            // Make sure we can actually search.
+            if (this._settings.searchTerms.Count <= 0)
+            {
+                _log.Error("Tried to search for a song with no valid search terms...");
+                SortSongName(levels);
+                return;
+            }
+            string searchTerm = this._settings.searchTerms[0];
+            if (String.IsNullOrEmpty(searchTerm))
+            {
+                _log.Error("Empty search term entered.");
+                SortSongName(levels);
+                return;
+            }
+
+            _log.Info("Filtering song list by search term: {0}", searchTerm);
+            //_originalSongs.ForEach(x => _log.Debug($"{x.songName} {x.songSubName} {x.songAuthorName}".ToLower().Contains(searchTerm.ToLower()).ToString()));
+
+            _filteredSongs = levels
+                .Where(x => $"{x.songName} {x.songSubName} {x.songAuthorName}".ToLower().Contains(searchTerm.ToLower()))
+                .ToList();
+        }
+
+        private void FilterPlaylist()
+        {
+            _log.Debug("Filtering songs for playlist: {0}", this.CurrentPlaylist);
+            List<String> playlistNameListOrdered = this.CurrentPlaylist.songs.Select(x => x.songName).Distinct().ToList();
+            Dictionary<String, int> songNameToIndex = playlistNameListOrdered.Select((val, index) => new { Index = index, Value = val }).ToDictionary(i => i.Value, i => i.Index);
+            HashSet<String> songNames = new HashSet<String>(playlistNameListOrdered);
+            SongLoaderPlugin.OverrideClasses.CustomLevelCollectionsForGameplayModes collections = SongLoaderPlugin.SongLoader.Instance.GetPrivateField<SongLoaderPlugin.OverrideClasses.CustomLevelCollectionsForGameplayModes>("_customLevelCollectionsForGameplayModes");
+            List<StandardLevelSO> songList = collections.GetLevels(_currentGamePlayMode).Where(x => songNames.Contains(x.songName)).ToList();
+            _log.Debug("\tMatching songs found for playlist: {0}", songList.Count);
+            _originalSongs = songList;
+            _filteredSongs = songList
+                .OrderBy(x => songNameToIndex[x.songName])
                 .ToList();
         }
 
         private void SortOriginal(List<StandardLevelSO> levels)
         {
             _log.Info("Sorting song list as original");
-            _sortedSongs = levels
+            _sortedSongs = levels;/*levels
                 .AsQueryable()
                 .OrderByDescending(x => _weights.ContainsKey(x.levelID) ? _weights[x.levelID] : 0)
                 .ThenBy(x => x.songName)
-                .ToList();
+                .ToList();*/
         }
 
         private void SortNewest(List<StandardLevelSO> levels)
@@ -683,34 +734,7 @@ namespace SongBrowserPlugin
                 .AsQueryable()
                 .OrderBy(x => rnd.Next())
                 .ToList();
-        }
-
-        private void SortSearch(List<StandardLevelSO> levels)
-        {
-            // Make sure we can actually search.
-            if (this._settings.searchTerms.Count <= 0)
-            {
-                _log.Error("Tried to search for a song with no valid search terms...");
-                SortSongName(levels);
-                return;
-            }
-            string searchTerm = this._settings.searchTerms[0];
-            if (String.IsNullOrEmpty(searchTerm))
-            {
-                _log.Error("Empty search term entered.");
-                SortSongName(levels);
-                return;
-            }
-
-            _log.Info("Sorting song list by search term: {0}", searchTerm);
-            //_originalSongs.ForEach(x => _log.Debug($"{x.songName} {x.songSubName} {x.songAuthorName}".ToLower().Contains(searchTerm.ToLower()).ToString()));
-
-            _sortedSongs = levels
-                .AsQueryable()
-                .Where(x => $"{x.songName} {x.songSubName} {x.songAuthorName}".ToLower().Contains(searchTerm.ToLower()))
-                .ToList();
-            //_sortedSongs.ForEach(x => _log.Debug(x.levelID));
-        }
+        }        
 
         private void SortSongName(List<StandardLevelSO> levels)
         {
@@ -721,20 +745,5 @@ namespace SongBrowserPlugin
                 .ThenBy(x => x.songAuthorName)
                 .ToList();
         }
-
-        private void SortPlaylist()
-        {
-            _log.Debug("Showing songs for playlist: {0}", this.CurrentPlaylist);
-            List<String> playlistNameListOrdered = this.CurrentPlaylist.songs.Select(x => x.songName).Distinct().ToList();
-            Dictionary<String, int> songNameToIndex = playlistNameListOrdered.Select((val, index) => new { Index = index, Value = val }).ToDictionary(i => i.Value, i => i.Index);
-            HashSet<String> songNames = new HashSet<String>(playlistNameListOrdered);
-            SongLoaderPlugin.OverrideClasses.CustomLevelCollectionsForGameplayModes collections = SongLoaderPlugin.SongLoader.Instance.GetPrivateField<SongLoaderPlugin.OverrideClasses.CustomLevelCollectionsForGameplayModes>("_customLevelCollectionsForGameplayModes");
-            List<StandardLevelSO> songList = collections.GetLevels(_currentGamePlayMode).Where(x => songNames.Contains(x.songName)).ToList();
-            _log.Debug("\tMatching songs found for playlist: {0}", songList.Count);
-            _sortedSongs = songList
-                .AsQueryable()
-                .OrderBy(x => songNameToIndex[x.songName])
-                .ToList();
-        }
     }
 }

+ 1 - 0
SongBrowserPlugin/SongBrowserPlugin.csproj

@@ -119,6 +119,7 @@
     <Compile Include="UI\CustomUIKeyboard.cs" />
     <Compile Include="UI\SearchKeyboardViewController.cs" />
     <Compile Include="UI\SongBrowserUI.cs" />
+    <Compile Include="UI\SongFilterButton.cs" />
     <Compile Include="UI\SongSortButton.cs" />
     <Compile Include="UI\UIBuilder.cs" />
   </ItemGroup>

+ 1 - 1
SongBrowserPlugin/UI/Base64Sprites.cs

@@ -35,7 +35,7 @@ namespace SongBrowserPlugin.UI
                 Texture2D tex = Base64ToTexture2D(base64);
                 s = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), (Vector2.one / 2f));
             }
-            catch (Exception e)
+            catch (Exception)
             {
                 Console.WriteLine("Exception loading texture from base64 data.");
                 s = null;

+ 113 - 84
SongBrowserPlugin/UI/SongBrowserUI.cs

@@ -39,8 +39,7 @@ namespace SongBrowserPlugin.UI
 
         // New UI Elements
         private List<SongSortButton> _sortButtonGroup;
-        private Button _searchButton;
-        private Button _playlistButton;
+        private List<SongFilterButton> _filterButtonGroup;
         private Button _addFavoriteButton;
         private SimpleDialogPromptViewController _simpleDialogPromptViewControllerPrefab;
         private SimpleDialogPromptViewController _deleteDialog;
@@ -148,6 +147,7 @@ namespace SongBrowserPlugin.UI
                 RectTransform otherButtonTransform = this._levelDetailViewController.transform as RectTransform;
                 Button sortButtonTemplate = _playButton;
                 Button otherButtonTemplate = Resources.FindObjectsOfTypeAll<Button>().First(x => (x.name == "QuitButton"));
+                Sprite arrowIcon = SongBrowserApplication.Instance.CachedIcons["ArrowIcon"];
 
                 // Resize some of the UI
                 _tableViewRectTransform = _levelListViewController.GetComponentsInChildren<RectTransform>().First(x => x.name == "TableViewContainer");
@@ -162,79 +162,69 @@ namespace SongBrowserPlugin.UI
 
                 // Create Sorting Songs By-Buttons
                 _log.Debug("Creating sort by buttons...");
-                
-                Sprite arrowIcon = SongBrowserApplication.Instance.CachedIcons["ArrowIcon"];
-
+                                
                 float fontSize = 2.35f;
-                float buttonWidth = 13.5f;
-                float buttonHeight = 5.250f;
+                float buttonWidth = 13.50f;
+                float buttonHeight = 5.5f;
                 float buttonX = -61;
                 float buttonY = 74.5f;
 
-                string[] buttonNames = new string[]
+                string[] sortButtonNames = new string[]
                 {
-                    "Favorite", "Song", "Author", "Original", "Newest", "Plays", "Difficult", "Random"
+                    "Song", "Author", "Original", "Newest", "Plays", "Difficult", "Random"
                 };
 
                 SongSortMode[] sortModes = new SongSortMode[]
                 {
-                    SongSortMode.Favorites, SongSortMode.Default, SongSortMode.Author, SongSortMode.Original, SongSortMode.Newest, SongSortMode.PlayCount, SongSortMode.Difficulty, SongSortMode.Random
-                };
-
-                System.Action<SongSortMode>[] onClickEvents = new Action<SongSortMode>[]
-                {
-                    onSortButtonClickEvent, onSortButtonClickEvent, onSortButtonClickEvent, onSortButtonClickEvent, onSortButtonClickEvent, onSortButtonClickEvent, onSortButtonClickEvent, onSortButtonClickEvent
+                    SongSortMode.Default, SongSortMode.Author, SongSortMode.Original, SongSortMode.Newest, SongSortMode.PlayCount, SongSortMode.Difficulty, SongSortMode.Random
                 };
 
                 _sortButtonGroup = new List<SongSortButton>();
-                for (int i = 0; i < buttonNames.Length; i++)
+                for (int i = 0; i < sortButtonNames.Length; i++)
                 {
-                    _sortButtonGroup.Add(UIBuilder.CreateSortButton(sortButtonTransform, sortButtonTemplate, arrowIcon, 
-                        buttonNames[i], 
+                    _sortButtonGroup.Add(UIBuilder.CreateSortButton(sortButtonTransform, sortButtonTemplate, arrowIcon,
+                        sortButtonNames[i], 
                         fontSize, 
                         buttonX + (buttonWidth * i), 
                         buttonY, 
                         buttonWidth, 
                         buttonHeight, 
-                        sortModes[i], 
-                        onClickEvents[i]));
+                        sortModes[i],
+                        onSortButtonClickEvent));
                 }
 
-                // Create playlist button
+                // Create filter buttons
+                float filterButtonX = buttonX + (buttonWidth * (sortButtonNames.Length - 1)) + (buttonWidth / 2.0f) + 2.5f;
                 Vector2 iconButtonSize = new Vector2(5.5f, buttonHeight);
-                Vector2 playlistButtonSize = new Vector2(5.5f, buttonHeight);
-                float playlistButtonX = buttonX + (buttonWidth * (buttonNames.Length - 1)) + (buttonWidth / 2.0f) + 2.5f;                
                 Sprite playlistSprite = Base64Sprites.Base64ToSprite(Base64Sprites.PlaylistIcon);
-                _playlistButton = UIBuilder.CreateIconButton(sortButtonTransform, sortButtonTemplate, playlistSprite,
-                    new Vector2(playlistButtonX, buttonY),
-                    new Vector2(iconButtonSize.x, iconButtonSize.y),
-                    new Vector2(0, 0),
-                    new Vector2(3.5f, 3.5f),
-                    new Vector2(1.0f, 1.0f),
-                    0.0f);
-                _playlistButton.onClick.AddListener(delegate ()
-                {
-                    onPlaylistButtonClickEvent(SongSortMode.Search);
-                });
-                buttonX += iconButtonSize.x;
-
-                // Create search button                
-                float searchButtonX = playlistButtonX + iconButtonSize.x;
                 Sprite searchSprite = Base64Sprites.Base64ToSprite(Base64Sprites.SearchIcon);
-                _searchButton = UIBuilder.CreateIconButton(sortButtonTransform, sortButtonTemplate, searchSprite,
-                    new Vector2(searchButtonX, buttonY),
-                    new Vector2(iconButtonSize.x, iconButtonSize.y),
-                    new Vector2(0, 0),
-                    new Vector2(3.5f, 3.5f),
-                    new Vector2(1.0f, 1.0f),
-                    0.0f);                
-                _searchButton.onClick.AddListener(delegate()
-                {
-                    onSearchButtonClickEvent(SongSortMode.Search);
-                });
-                buttonX += iconButtonSize.x;
 
+                List<Tuple<SongFilterMode, UnityEngine.Events.UnityAction, Sprite>> filterButtonSetup = new List<Tuple<SongFilterMode, UnityEngine.Events.UnityAction, Sprite>>()
+                {
+                    Tuple.Create<SongFilterMode, UnityEngine.Events.UnityAction, Sprite>(SongFilterMode.Favorites, onFavoriteFilterButtonClickEvent, _addFavoriteSprite),
+                    Tuple.Create<SongFilterMode, UnityEngine.Events.UnityAction, Sprite>(SongFilterMode.Playlist, onPlaylistButtonClickEvent, playlistSprite),
+                    Tuple.Create<SongFilterMode, UnityEngine.Events.UnityAction, Sprite>(SongFilterMode.Search, onSearchButtonClickEvent, searchSprite),
+                };
 
+                _filterButtonGroup = new List<SongFilterButton>();
+                for (int i = 0; i < filterButtonSetup.Count; i++)
+                {
+                    Tuple<SongFilterMode, UnityEngine.Events.UnityAction, Sprite> t = filterButtonSetup[i];
+                    Button b = UIBuilder.CreateIconButton(sortButtonTransform, sortButtonTemplate,
+                        t.Item3,
+                        new Vector2(filterButtonX + (iconButtonSize.x * i), buttonY),
+                        new Vector2(iconButtonSize.x, iconButtonSize.y),
+                        new Vector2(0, 0),
+                        new Vector2(3.5f, 3.5f),
+                        new Vector2(1.0f, 1.0f),
+                        0);
+                    SongFilterButton filterButton = new SongFilterButton();
+                    filterButton.Button = b;
+                    filterButton.FilterMode = t.Item1;
+                    b.onClick.AddListener(t.Item2);
+                    _filterButtonGroup.Add(filterButton);
+                }
+               
                 // Create Add to Favorites Button
                 Vector2 addFavoritePos = new Vector2(40f, (sortButtonTemplate.transform as RectTransform).anchoredPosition.y);
                 _addFavoriteButton = UIBuilder.CreateIconButton(otherButtonTransform, otherButtonTemplate, null, 
@@ -300,7 +290,7 @@ namespace SongBrowserPlugin.UI
 
                     // Create up folder button
                     _upFolderButton = UIBuilder.CreateIconButton(sortButtonTransform, sortButtonTemplate, arrowIcon,
-                        new Vector2(searchButtonX + iconButtonSize.x, buttonY),
+                        new Vector2(filterButtonX + iconButtonSize.x, buttonY),
                         new Vector2(iconButtonSize.x, iconButtonSize.y),
                         new Vector2(0f, 0f),
                         new Vector2(0.85f, 0.85f),
@@ -360,12 +350,41 @@ namespace SongBrowserPlugin.UI
         }
 
         /// <summary>
-        /// Search button clicked.  
+        /// Filter by favorites.
+        /// </summary>
+        private void onFavoriteFilterButtonClickEvent()
+        {
+            _log.Debug("Filter button - {0} - pressed.", SongFilterMode.Favorites.ToString());
+
+            if (_model.Settings.filterMode != SongFilterMode.Favorites)
+            {
+                _model.Settings.filterMode = SongFilterMode.Favorites;
+            }
+            else
+            {
+                _model.Settings.filterMode = SongFilterMode.None;
+            }
+            _model.Settings.Save();
+
+            UpdateSongList();
+            RefreshSongList();
+        }
+
+        /// <summary>
+        /// Filter button clicked.  
         /// </summary>
         /// <param name="sortMode"></param>
-        private void onSearchButtonClickEvent(SongSortMode sortMode)
+        private void onSearchButtonClickEvent()
         {
-            _model.Settings.sortMode = sortMode;
+            _log.Debug("Filter button - {0} - pressed.", SongFilterMode.Search.ToString());
+            if (_model.Settings.filterMode != SongFilterMode.Search)
+            {
+                _model.Settings.filterMode = SongFilterMode.Search;
+            }
+            else
+            {
+                _model.Settings.filterMode = SongFilterMode.None;
+            }
             _model.Settings.Save();
 
             this.ShowSearchKeyboard();
@@ -375,14 +394,24 @@ namespace SongBrowserPlugin.UI
         /// Display the playlist selector.
         /// </summary>
         /// <param name="sortMode"></param>
-        private void onPlaylistButtonClickEvent(SongSortMode sortMode)
+        private void onPlaylistButtonClickEvent()
         {
-            _log.Debug("Sort button - {0} - pressed.", sortMode.ToString());
+            _log.Debug("Filter button - {0} - pressed.", SongFilterMode.Playlist.ToString());
             _model.LastSelectedLevelId = null;
 
-            PlaylistFlowCoordinator view = UIBuilder.CreateFlowCoordinator<PlaylistFlowCoordinator>("PlaylistFlowCoordinator");
-            view.didSelectPlaylist += HandleDidSelectPlaylist;
-            view.Present(_levelSelectionNavigationController);
+            if (_model.Settings.filterMode != SongFilterMode.Playlist)
+            {
+                PlaylistFlowCoordinator view = UIBuilder.CreateFlowCoordinator<PlaylistFlowCoordinator>("PlaylistFlowCoordinator");
+                view.didSelectPlaylist += HandleDidSelectPlaylist;
+                view.Present(_levelSelectionNavigationController);
+            }
+            else
+            {
+                _model.Settings.filterMode = SongFilterMode.None;
+                _model.Settings.Save();
+                UpdateSongList();
+                RefreshSongList();
+            }
         }
 
         /// <summary>
@@ -580,7 +609,7 @@ namespace SongBrowserPlugin.UI
         private void HandleDidSelectPlaylist(Playlist p)
         {
             _log.Debug("Showing songs for playlist: {0}", p.playlistTitle);
-            _model.Settings.sortMode = SongSortMode.Playlist;
+            _model.Settings.filterMode = SongFilterMode.Playlist;
             _model.CurrentPlaylist = p;
             _model.Settings.Save();
             this.UpdateSongList();
@@ -731,23 +760,15 @@ namespace SongBrowserPlugin.UI
                 }
             }    
             
-            if (_model.Settings.sortMode == SongSortMode.Search)
-            {
-                UIBuilder.SetButtonBorder(ref _searchButton, Color.green);
-            }
-            else
-            {
-                UIBuilder.SetButtonBorder(ref _searchButton, Color.clear);
-            }
-
-            if (_model.Settings.sortMode == SongSortMode.Playlist)
-            {
-                UIBuilder.SetButtonBorder(ref _playlistButton, Color.green);
-            }
-            else
+            // refresh filter buttons
+            foreach (SongFilterButton filterButton in _filterButtonGroup)
             {
-                UIBuilder.SetButtonBorder(ref _playlistButton, Color.clear);
-            }
+                UIBuilder.SetButtonBorder(ref filterButton.Button, Color.clear);
+                if (filterButton.FilterMode == _model.Settings.filterMode)
+                {
+                    UIBuilder.SetButtonBorder(ref filterButton.Button, Color.green);
+                }
+            }           
         }
 
         /// <summary>
@@ -813,6 +834,7 @@ namespace SongBrowserPlugin.UI
                 }
 
                 RefreshSortButtonUI();
+                RefreshQuickScrollButtons();
             }
             catch (Exception e)
             {
@@ -878,21 +900,28 @@ namespace SongBrowserPlugin.UI
                         _sortButtonGroup[_sortButtonLastPushedIndex].Button.onClick.Invoke();
                     }
 
-                    if (Input.GetKeyDown(KeyCode.S))
-                    {
-                        onSearchButtonClickEvent(SongSortMode.Search);
-                    }
-
                     // select current sort mode again (toggle inverting)
                     if (Input.GetKeyDown(KeyCode.Y))
                     {
                         _sortButtonGroup[_sortButtonLastPushedIndex].Button.onClick.Invoke();
                     }
 
-                    // playlists
+                    // filter playlists
                     if (Input.GetKeyDown(KeyCode.P))
                     {
-                        _playlistButton.onClick.Invoke();
+                        onPlaylistButtonClickEvent();
+                    }
+
+                    // filter search
+                    if (Input.GetKeyDown(KeyCode.S))
+                    {
+                        onSearchButtonClickEvent();
+                    }
+
+                    // filter favorites
+                    if (Input.GetKeyDown(KeyCode.F))
+                    {
+                        onFavoriteFilterButtonClickEvent();
                     }
 
                     // delete
@@ -950,7 +979,7 @@ namespace SongBrowserPlugin.UI
                     }
 
                     // add to favorites
-                    if (Input.GetKeyDown(KeyCode.F))
+                    if (Input.GetKeyDown(KeyCode.KeypadPlus))
                     {
                         ToggleSongInFavorites();
                     }