Improved tab support

- Ability to specify position of auto & custom tabs (top, left, right)
- Highlighting around selected tab
This commit is contained in:
tverona1
2019-08-04 13:09:49 -07:00
parent f14cc15164
commit 81e778f281
12 changed files with 5718 additions and 567 deletions
+9 -13
View File
@@ -12,10 +12,11 @@ namespace QuestAppLauncher
[Serializable]
public class Config
{
// Supported category types
public const string Category_None = "none";
public const string Category_Auto = "auto";
public const string Category_Custom = "custom";
// Supported category mode
public const string Category_Off = "off";
public const string Category_Top = "top";
public const string Category_Left = "left";
public const string Category_Right = "right";
/// <summary>
/// Grid size
@@ -33,16 +34,11 @@ namespace QuestAppLauncher
// Whether to show 2D apps
public bool show2D = false;
// Whether to only show apps that are explicitly specified in appnames.txt file.
// If true, this will not show installed apps that are not in appnames.txt. This
// is useful for organizing the launcher with a highly curated list of apps.
public bool showOnlyCustom = false;
// Auto Category: Apps are automatically categorized into 3 tabs - Quest, Go/GearVr, 2D
public string autoCategory = Category_Top;
// Category types: "none", "auto", "custom":
// - none: No categories - all apps are listed in a single pane
// - auto: Apps are automatically categorized into 3 tabs - Quest, Go/GearVr, 2D
// - custom: Apps are categorized according to appnames.txt file
public string categoryType = Category_Auto;
// Custom Category: Apps are categorized according to appnames.txt file
public string customCategory = Category_Right;
}
/// <summary>
+150 -104
View File
@@ -42,11 +42,15 @@ namespace QuestAppLauncher
// Scroll container game object
public GameObject scrollContainer;
// Tab container
public GameObject tabContainer;
// Tab containers
public GameObject topTabContainer;
public GameObject leftTabContainer;
public GameObject rightTabContainer;
// Tab container
public GameObject tabContainerContent;
public GameObject topTabContainerContent;
public GameObject leftTabContainerContent;
public GameObject rightTabContainerContent;
// Tracking space
public GameObject trackingSpace;
@@ -64,10 +68,12 @@ namespace QuestAppLauncher
private Coroutine populateCoroutine;
// Built-in tab names
private const string Tab_None = "None";
private const string Tab_Quest = "Quest";
private const string Tab_Go = "Go/Gear";
private const string Tab_2D = "2D";
private const string Tab_All = "All";
private static readonly string[] Auto_Tabs = { Tab_Quest, Tab_Go, Tab_2D };
#region MonoBehaviour handler
@@ -158,7 +164,7 @@ namespace QuestAppLauncher
return false;
}
public void SetGridSize(GameObject gridContent, int rows, int cols)
public Vector2 SetGridSize(GameObject gridContent, int rows, int cols)
{
// Make sure grid size have sane value
cols = Math.Min(cols, 10);
@@ -185,8 +191,10 @@ namespace QuestAppLauncher
Debug.Log(string.Format("Grid size calculated width x height: {0} x {1}", width, height));
// Adjust grid container rect transform
var size = new Vector2(width, height);
var gridTransform = this.panelContainer.GetComponent<RectTransform>();
gridTransform.sizeDelta = new Vector2(width, height);
gridTransform.sizeDelta = size;
// Adjust grid container Y position to maintain constant height.
// TODO: Figure out a way to adjust UI to avoid this calculation in code
@@ -194,6 +202,8 @@ namespace QuestAppLauncher
(float)((gridTransform.rect.height - 2000) / 2.0),
gridTransform.anchoredPosition3D.z);
gridTransform.anchoredPosition3D = gridPosition;
return size;
}
public void StartPopulate()
@@ -284,8 +294,8 @@ namespace QuestAppLauncher
tabName = Tab_Go;
}
apps.Add(packageName, new ProcessedApp { PackageName = packageName, Index = i, AutoTabName = tabName, Tab1Name = tabName, AppName = appName });
Debug.LogFormat("[{0}] package: {1}, name: {2}, tab: {3}", i, packageName, appName, tabName);
apps.Add(packageName, new ProcessedApp { PackageName = packageName, Index = i, AutoTabName = tabName, AppName = appName });
Debug.LogFormat("[{0}] package: {1}, name: {2}, auto tab: {3}", i, packageName, appName, tabName);
yield return null;
}
@@ -317,6 +327,15 @@ namespace QuestAppLauncher
var packageName = entry[0];
var appName = entry[1];
if (!apps.ContainsKey(packageName))
{
// App is not installed, so skip
continue;
}
// Get the custom tab names, if any
string autoTabName = null;
var tab1 = entry.Length > 2 ? entry[2] : null;
var tab2 = entry.Length > 3 ? entry[3] : null;
@@ -330,10 +349,22 @@ namespace QuestAppLauncher
tab2 = null;
}
if (!apps.ContainsKey(packageName))
if (tab1 != null && tab2 != null && tab1.Equals(tab2, StringComparison.OrdinalIgnoreCase))
{
// App is not installed, so skip
continue;
tab2 = null;
}
// Override auto tabe name if custom name matches built-in tab name
if (tab1 != null && Auto_Tabs.Contains(tab1, StringComparer.OrdinalIgnoreCase))
{
autoTabName = tab1;
tab1 = null;
}
if (tab2 != null && Auto_Tabs.Contains(tab2, StringComparer.OrdinalIgnoreCase))
{
autoTabName = tab2;
tab2 = null;
}
// Update entry
@@ -342,9 +373,9 @@ namespace QuestAppLauncher
PackageName = apps[entry[0]].PackageName,
Index = apps[entry[0]].Index,
AppName = appName,
AutoTabName = apps[entry[0]].AutoTabName,
AutoTabName = autoTabName ?? apps[entry[0]].AutoTabName,
Tab1Name = tab1 ?? apps[entry[0]].Tab1Name,
Tab2Name = tab2,
Tab2Name = tab2 ?? apps[entry[0]].Tab2Name,
IsOverride = true
};
}
@@ -388,56 +419,120 @@ namespace QuestAppLauncher
Dictionary<string, ProcessedApp> apps,
Dictionary<string, string> iconOverrides)
{
// Destroy existing scrollviews and tabs
for (int i = 0; i < this.tabContainerContent.transform.childCount; i++)
// Set up tabs
var topTabs = new List<string>();
var leftTabs = new List<string>();
var rightTabs = new List<string>();
// Set auto tabs
if (config.autoCategory.Equals(Config.Category_Top, StringComparison.OrdinalIgnoreCase))
{
Destroy(this.tabContainerContent.transform.GetChild(i).gameObject);
Destroy(this.scrollContainer.transform.GetChild(i).gameObject);
topTabs.AddRange(Auto_Tabs);
}
else if (config.autoCategory.Equals(Config.Category_Left, StringComparison.OrdinalIgnoreCase))
{
leftTabs.AddRange(Auto_Tabs);
}
else if (config.autoCategory.Equals(Config.Category_Right, StringComparison.OrdinalIgnoreCase))
{
rightTabs.AddRange(Auto_Tabs);
}
List<string> tabs;
bool isNoneTab = false;
bool isAutoTab = false;
// Set custom tabs, sorted alphabetically
var customTabs = apps.Where(x => null != x.Value.Tab1Name).Select(x => x.Value.Tab1Name).Union(apps
.Where(x => null != x.Value.Tab2Name).Select(x => x.Value.Tab2Name))
.Distinct(StringComparer.CurrentCultureIgnoreCase).ToList();
customTabs.Sort();
if (config.categoryType.Equals(Config.Category_None, StringComparison.OrdinalIgnoreCase))
if (config.customCategory.Equals(Config.Category_Top, StringComparison.OrdinalIgnoreCase))
{
// No tabs - use special "None" tab
tabs = new List<string>();
tabs.Add(Tab_None);
isNoneTab = true;
topTabs.AddRange(customTabs);
}
else if (config.categoryType.Equals(Config.Category_Auto, StringComparison.OrdinalIgnoreCase))
else if (config.customCategory.Equals(Config.Category_Left, StringComparison.OrdinalIgnoreCase))
{
// Add built-in tabs
tabs = new List<string>();
tabs.Add(Tab_Quest);
tabs.Add(Tab_Go);
tabs.Add(Tab_2D);
isAutoTab = true;
leftTabs.AddRange(customTabs);
}
else if (config.customCategory.Equals(Config.Category_Right, StringComparison.OrdinalIgnoreCase))
{
rightTabs.AddRange(customTabs);
}
// Add the "all" top tab
topTabs.Add(Tab_All);
// Process the tab containers
var gridContents = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase);
ProcessTabContainer(config, topTabs, this.topTabContainer, this.topTabContainerContent, true, gridContents);
ProcessTabContainer(config, leftTabs, this.leftTabContainer, this.leftTabContainerContent, false, gridContents);
ProcessTabContainer(config, rightTabs, this.rightTabContainer, this.rightTabContainerContent, false, gridContents);
// Set panel size, use any grid content for reference (since they are all the same size)
if (gridContents.Count > 0)
{
var size = SetGridSize(gridContents.First().Value, config.gridSize.rows, config.gridSize.cols);
// Adjust tab sizes
ResizeTabContent(this.topTabContainer.transform, size, topTabs.Count, true);
ResizeTabContent(this.leftTabContainer.transform, size, leftTabs.Count, false);
ResizeTabContent(this.rightTabContainer.transform, size, rightTabs.Count, false);
}
// Populate grid with app information (name & icon)
// Sort by app name
foreach (var app in apps.OrderBy(key => key.Value.AppName))
{
// Add to all tab
yield return AddCellToGrid(app.Value, gridContents[Tab_All].transform, iconOverrides, currentActivity);
// Add to auto (built-in) tabs
if (gridContents.ContainsKey(app.Value.AutoTabName))
{
yield return AddCellToGrid(app.Value, gridContents[app.Value.AutoTabName].transform, iconOverrides, currentActivity);
}
// Add to tab1
if (null != app.Value.Tab1Name && gridContents.ContainsKey(app.Value.Tab1Name))
{
yield return AddCellToGrid(app.Value, gridContents[app.Value.Tab1Name].transform, iconOverrides, currentActivity);
}
// Add to tab2
if (null != app.Value.Tab2Name && gridContents.ContainsKey(app.Value.Tab2Name))
{
yield return AddCellToGrid(app.Value, gridContents[app.Value.Tab2Name].transform, iconOverrides, currentActivity);
}
}
}
private void ResizeTabContent(Transform transform, Vector2 size, int childCount, bool isHorizontal)
{
var rect = transform.GetComponent<RectTransform>();
// Resize the transform
Vector2 newSize;
if (isHorizontal)
{
newSize = new Vector2(size.x, rect.rect.height);
}
else
{
// Construct list of custom tabs, sorted alphabetically and add built-in tabs up front
tabs = apps.Select(x => x.Value.Tab1Name).Union(
apps.Where(x => null != x.Value.Tab2Name).Select(x => x.Value.Tab2Name)).Distinct().ToList();
tabs.Sort();
if (tabs.Remove(Tab_2D))
{
tabs.Insert(0, Tab_2D);
}
if (tabs.Remove(Tab_Go))
{
tabs.Insert(0, Tab_Go);
}
if (tabs.Remove(Tab_Quest))
{
tabs.Insert(0, Tab_Quest);
}
newSize = new Vector2(rect.rect.width, size.y);
}
var gridContents = new Dictionary<string, GameObject>();
bool isFirstTab = true;
rect.sizeDelta = newSize;
// Resize box collider
var boxCollider = transform.GetComponent<BoxCollider>();
boxCollider.size = new Vector3(newSize.x, newSize.y, (float)0.05);
// Refresh tab prev / next buttons
transform.gameObject.GetComponent<ScrollButtonHandler>().RefreshScrollContent(childCount);
}
private void ProcessTabContainer(Config config, List<string> tabs, GameObject tabContainer,
GameObject tabContainerContent, bool setFirstTabActive, Dictionary<string, GameObject> gridContents)
{
// Create scroll views and tabs
foreach (string tabName in tabs)
{
@@ -447,73 +542,24 @@ namespace QuestAppLauncher
var scrollView = (GameObject)Instantiate(this.prefabScrollView, this.scrollContainer.transform);
var scrollRectOverride = scrollView.GetComponent<ScrollRectOverride>();
scrollRectOverride.trackingSpace = this.trackingSpace.transform;
scrollRectOverride.name = tabName;
var gridContent = scrollRectOverride.content.gameObject;
scrollView.SetActive(isFirstTab);
// Set grid size
SetGridSize(gridContent, config.gridSize.rows, config.gridSize.cols);
scrollView.SetActive(setFirstTabActive);
// Create tab
var tab = (GameObject)Instantiate(this.prefabTab, this.tabContainerContent.transform);
var tab = (GameObject)Instantiate(this.prefabTab, tabContainerContent.transform);
tab.GetComponentInChildren<TextMeshProUGUI>().text = tabName;
var toggle = tab.GetComponent<Toggle>();
toggle.isOn = isFirstTab;
toggle.group = this.tabContainerContent.GetComponent<ToggleGroup>();
toggle.isOn = setFirstTabActive;
toggle.group = this.panelContainer.GetComponent<ToggleGroup>();
toggle.onValueChanged.AddListener(scrollView.SetActive);
if (isNoneTab)
{
// Hide the special "None" tab
tab.SetActive(false);
}
isFirstTab = false;
setFirstTabActive = false;
// Record the grid content
gridContents[tabName] = scrollView.GetComponent<ScrollRect>().content.gameObject;
}
// Refresh tab prev / next buttons
this.tabContainer.GetComponent<ScrollButtonHandler>().RefreshScrollContent(tabs.Count);
this.tabContainer.GetComponent<ScrollRectColliderMask>().Refresh();
// Populate grid with app information (name & icon)
// Sort by app name
foreach (var app in apps.OrderBy(key => key.Value.AppName))
{
if (config.showOnlyCustom && !app.Value.IsOverride)
{
// Since showOnlyCustom is set, skip apps that are not in the appnames.txt file
Debug.LogFormat("Skipping non-Show Only Custom [{0}] Package: {1}, name: {2}",
app.Value.Index, app.Value.PackageName, app.Value.AppName);
continue;
}
if (isNoneTab)
{
// No tabs, so use the special "None" tab
yield return AddCellToGrid(app.Value, gridContents[Tab_None].transform, iconOverrides, currentActivity);
}
else if (isAutoTab)
{
// Add to auto (built-in) tabs
yield return AddCellToGrid(app.Value, gridContents[app.Value.AutoTabName].transform, iconOverrides, currentActivity);
}
else
{
// Add to tab1
yield return AddCellToGrid(app.Value, gridContents[app.Value.Tab1Name].transform, iconOverrides, currentActivity);
if (null != app.Value.Tab2Name)
{
// Tab2 exists, so add to tab2
yield return AddCellToGrid(app.Value, gridContents[app.Value.Tab2Name].transform, iconOverrides, currentActivity);
}
}
}
}
private IEnumerator AddCellToGrid(ProcessedApp app, Transform transform,
+122
View File
@@ -0,0 +1,122 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
namespace QuestAppLauncher
{
public class ScrollButtonHandler : MonoBehaviour
{
// Child object, used to determine size
public GameObject prefabChild;
// Scroll content
public RectTransform content;
[Tooltip("Button to go to the previous page")]
public Button PrevButton;
[Tooltip("Button to go to the next page")]
public Button NextButton;
[Tooltip("Whether tabs are horizontal (true) or vertical (false)")]
public bool isHorizontal;
// Size of child object (either width or height)
private float childSize;
// Current rect transform
private RectTransform rectTransform;
private const float CmToInch = 2.54f;
private const float DragThresholdCM = 50f;
void Start()
{
this.PrevButton.onClick.AddListener(() => { ScrollPrev(); });
this.NextButton.onClick.AddListener(() => { ScrollNext(); });
this.PrevButton.gameObject.SetActive(false);
this.NextButton.gameObject.SetActive(false);
this.rectTransform = GetComponent<RectTransform>();
this.childSize = this.isHorizontal ? this.prefabChild.GetComponent<RectTransform>().sizeDelta.x :
this.prefabChild.GetComponent<RectTransform>().sizeDelta.y;
RefreshScrollContent(0);
SetPhysicalDragThreshold();
}
// Update is called once per frame
void Update()
{
}
public void RefreshScrollContent(int numChildren)
{
Canvas.ForceUpdateCanvases();
float contentSize = numChildren * this.childSize;
var recTransformSize = this.isHorizontal ? this.rectTransform.sizeDelta.x :
this.rectTransform.sizeDelta.y;
if (recTransformSize >= contentSize)
{
// Viewport can fit the content, so hide the buttons
this.PrevButton.gameObject.SetActive(false);
this.NextButton.gameObject.SetActive(false);
}
else
{
this.PrevButton.gameObject.SetActive(true);
this.NextButton.gameObject.SetActive(true);
}
}
public void SetPhysicalDragThreshold()
{
Debug.LogFormat("Drag threshold: {0}", EventSystem.current.pixelDragThreshold);
EventSystem.current.pixelDragThreshold = (int)(DragThresholdCM * Screen.dpi / CmToInch);
Debug.LogFormat("Updated drag threshold: {0}", EventSystem.current.pixelDragThreshold);
}
public void ScrollPrev()
{
Vector2 newPosition;
if (this.isHorizontal)
{
newPosition = new Vector2(this.content.transform.localPosition.x + this.childSize,
this.content.transform.localPosition.y);
}
else
{
newPosition = new Vector2(this.content.transform.localPosition.x,
this.content.transform.localPosition.y - this.childSize);
}
this.content.transform.localPosition = newPosition;
}
public void ScrollNext()
{
Vector2 newPosition = new Vector2(this.content.transform.localPosition.x - this.childSize, this.content.transform.localPosition.y);
if (this.isHorizontal)
{
newPosition = new Vector2(this.content.transform.localPosition.x - this.childSize,
this.content.transform.localPosition.y);
}
else
{
newPosition = new Vector2(this.content.transform.localPosition.x,
this.content.transform.localPosition.y + this.childSize);
}
this.content.transform.localPosition = newPosition;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 390013d26c40ccd4ab21b46bd10bf9dc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+61
View File
@@ -0,0 +1,61 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ControllerSelection;
public class ScrollRectColliderMask : MonoBehaviour
{
// Content
public RectTransform content;
// Tracking space used for ray cast
public Transform trackingSpace = null;
// Box collider used for ray cast
private BoxCollider boxCollider = null;
// Whether the pointer is within bounds of the scroll rect
private bool isInBounds = true;
private bool isInitialized = false;
private OVRInput.Controller activeController = OVRInput.Controller.None;
// Start is called before the first frame update
void Start()
{
this.boxCollider = GetComponent<BoxCollider>();
}
// Update is called once per frame
void Update()
{
this.activeController = OVRInputHelpers.GetControllerForButton(OVRInput.Button.PrimaryIndexTrigger, this.activeController);
Ray pointer = OVRInputHelpers.GetSelectionRay(this.activeController, this.trackingSpace);
RaycastHit hit;
if (this.boxCollider.Raycast(pointer, out hit, 500))
{
// We got a hit in the scroll view. Check if we're already within the bounds - if so, do nothing.
if (!isInBounds)
{
// We entered the scroll view, so enable box colliders on children.
foreach (var boxCollider in this.content.gameObject.GetComponentsInChildren<BoxCollider>())
{
boxCollider.enabled = true;
}
isInBounds = true;
}
}
else if (isInBounds)
{
// We are outside the scroll view and were previously inside, so disable box colliders on children.
foreach (var boxCollider in this.content.gameObject.GetComponentsInChildren<BoxCollider>())
{
boxCollider.enabled = false;
}
isInBounds = false;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9f2a3df6684af7245a2512d708d72e62
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+74 -30
View File
@@ -20,11 +20,16 @@ namespace QuestAppLauncher
public GameObject gridRowsText;
public GameObject gridPopulation;
public GameObject show2DToggle;
public GameObject showOnlyCustomToggle;
public Toggle tabsNone;
public Toggle tabsAuto;
public Toggle tabsCustom;
public Toggle tabsAutoOff;
public Toggle tabsAutoTop;
public Toggle tabsAutoLeft;
public Toggle tabsAutoRight;
public Toggle tabsCustomOff;
public Toggle tabsCustomTop;
public Toggle tabsCustomLeft;
public Toggle tabsCustomRight;
private bool deletedHiddenAppsFile = false;
@@ -56,21 +61,40 @@ namespace QuestAppLauncher
// Set 2D toggle
this.show2DToggle.GetComponent<Toggle>().SetIsOnWithoutNotify(this.config.show2D);
// Set ShowOnlyCustom toggle
this.showOnlyCustomToggle.GetComponent<Toggle>().SetIsOnWithoutNotify(this.config.showOnlyCustom);
// Set tab mode
if (this.config.categoryType.Equals(Config.Category_None, StringComparison.OrdinalIgnoreCase))
// Set auto tab mode
if (this.config.autoCategory.Equals(Config.Category_Top, StringComparison.OrdinalIgnoreCase))
{
this.tabsNone.isOn = true;
this.tabsAutoTop.isOn = true;
}
else if (this.config.categoryType.Equals(Config.Category_Auto, StringComparison.OrdinalIgnoreCase))
else if (this.config.autoCategory.Equals(Config.Category_Left, StringComparison.OrdinalIgnoreCase))
{
this.tabsAuto.isOn = true;
this.tabsAutoLeft.isOn = true;
}
else if (this.config.autoCategory.Equals(Config.Category_Right, StringComparison.OrdinalIgnoreCase))
{
this.tabsAutoRight.isOn = true;
}
else
{
this.tabsCustom.isOn = true;
this.tabsAutoOff.isOn = true;
}
// Set custom tab mode
if (this.config.customCategory.Equals(Config.Category_Top, StringComparison.OrdinalIgnoreCase))
{
this.tabsCustomTop.isOn = true;
}
else if (this.config.customCategory.Equals(Config.Category_Left, StringComparison.OrdinalIgnoreCase))
{
this.tabsCustomLeft.isOn = true;
}
else if (this.config.customCategory.Equals(Config.Category_Right, StringComparison.OrdinalIgnoreCase))
{
this.tabsCustomRight.isOn = true;
}
else
{
this.tabsCustomOff.isOn = true;
}
}
@@ -134,33 +158,53 @@ namespace QuestAppLauncher
saveConfig = true;
}
// Update ShowOnlyCustom toggle
var showOnlyCustom = this.showOnlyCustomToggle.GetComponent<Toggle>().isOn;
if (showOnlyCustom != this.config.showOnlyCustom)
// Update auto tab mode
string tabAutoMode;
if (this.tabsAutoTop.isOn)
{
this.config.showOnlyCustom = showOnlyCustom;
saveConfig = true;
tabAutoMode = Config.Category_Top;
}
// Update tabbing
string tabMode;
if (this.tabsNone.isOn)
else if (this.tabsAutoLeft.isOn)
{
tabMode = Config.Category_None;
tabAutoMode = Config.Category_Left;
}
else if (this.tabsAuto.isOn)
else if (this.tabsAutoRight.isOn)
{
tabMode = Config.Category_Auto;
tabAutoMode = Config.Category_Right;
}
else
{
tabMode = Config.Category_Custom;
tabAutoMode = Config.Category_Off;
}
if (!this.config.categoryType.Equals(tabMode, StringComparison.OrdinalIgnoreCase))
if (!this.config.autoCategory.Equals(tabAutoMode, StringComparison.OrdinalIgnoreCase))
{
this.tabsNone.isOn = true;
this.config.categoryType = tabMode;
this.config.autoCategory = tabAutoMode;
saveConfig = true;
}
// Update auto tab mode
string tabCustomMode;
if (this.tabsCustomTop.isOn)
{
tabCustomMode = Config.Category_Top;
}
else if (this.tabsCustomLeft.isOn)
{
tabCustomMode = Config.Category_Left;
}
else if (this.tabsCustomRight.isOn)
{
tabCustomMode = Config.Category_Right;
}
else
{
tabCustomMode = Config.Category_Off;
}
if (!this.config.customCategory.Equals(tabCustomMode, StringComparison.OrdinalIgnoreCase))
{
this.config.customCategory = tabCustomMode;
saveConfig = true;
}
@@ -174,7 +218,7 @@ namespace QuestAppLauncher
if (saveConfig || deletedHiddenAppsFile)
{
Debug.Log("Re-populating panel");
this.gridPopulation.GetComponent<GridPopulation>().StartPopulate();
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
}