From d30673f8a3ad1c3bd3ae3e4f32dcb329566edf33 Mon Sep 17 00:00:00 2001 From: tverona1 Date: Sun, 18 Aug 2019 15:47:06 -0700 Subject: [PATCH] Support for appnames.json format; support for launcher on Go - Added support for appnames.json format. Example entry: "com.HighVoltage.Crossbow":{"name": "Ballista", "category": "cat1", "category2" : "cat 2"}. - Set headtracking required to false to support launcher on Go. --- Assets/Plugins/Android/AndroidManifest.xml | 2 +- Assets/Scripts/AppProcessor.cs | 110 +++++++++++++++++++-- Assets/Scripts/AssetsDownloader.cs | 7 +- 3 files changed, 109 insertions(+), 10 deletions(-) diff --git a/Assets/Plugins/Android/AndroidManifest.xml b/Assets/Plugins/Android/AndroidManifest.xml index 34e4a61..a3cf07a 100644 --- a/Assets/Plugins/Android/AndroidManifest.xml +++ b/Assets/Plugins/Android/AndroidManifest.xml @@ -10,5 +10,5 @@ - + \ No newline at end of file diff --git a/Assets/Scripts/AppProcessor.cs b/Assets/Scripts/AppProcessor.cs index 277a546..19948b1 100644 --- a/Assets/Scripts/AppProcessor.cs +++ b/Assets/Scripts/AppProcessor.cs @@ -3,11 +3,17 @@ using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; using System.Threading.Tasks; using UnityEngine; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; namespace QuestAppLauncher { + /// + /// Class used to track details about an app + /// public class ProcessedApp { public int Index; @@ -21,8 +27,20 @@ namespace QuestAppLauncher public class AppProcessor { + /// + /// Class used to deserialize appnames.json entries + /// + [Serializable] + class JsonAppNamesEntry + { + public string Name; + public string Category; + public string Category2; + } + // File name of app name overrides - const string AppNameOverrideFileSearch = "appnames*.txt"; + const string AppNameOverrideTxtFileSearch = "appnames*.txt"; + const string AppNameOverrideJsonFileSearch = "appnames*.json"; // Icon pack search string const string IconPackSearch = "iconpack*.zip"; @@ -143,22 +161,102 @@ namespace QuestAppLauncher private static void ProcessAppNameOverrideFiles(Dictionary apps, string path) { + // Process appname*.json files, sorted by name + foreach (var filePath in Directory.GetFiles( + path, AppNameOverrideJsonFileSearch).OrderBy(f => f)) + { + ProcessAppNameOverrideJsonFile(apps, filePath); + } + // Process appname*.txt files, sorted by name foreach (var filePath in Directory.GetFiles( - path, AppNameOverrideFileSearch).OrderBy(f => f)) + path, AppNameOverrideTxtFileSearch).OrderBy(f => f)) { - ProcessAppNameOverrideFile(apps, filePath); + ProcessAppNameOverrideTxtFile(apps, filePath); } } - private static void ProcessAppNameOverrideFile(Dictionary apps, string appNameOverrideFilePath) + private static void ProcessAppNameOverrideJsonFile(Dictionary apps, string appNameOverrideFilePath) + { + // Override app names, if any + Debug.Log("Found file: " + appNameOverrideFilePath); + + try + { + var json = File.ReadAllText(appNameOverrideFilePath, Encoding.UTF8); + var jsonAppNames = JsonConvert.DeserializeObject>(json); + + foreach (var entry in jsonAppNames) + { + var packageName = entry.Key; + var appName = entry.Value.Name; + + if (!apps.ContainsKey(packageName)) + { + // App is not installed, so skip + continue; + } + + // Get the custom tab names, if any + string autoTabName = null; + var tab1 = entry.Value.Category; + var tab2 = entry.Value.Category2; + + if (tab1 != null && tab1.Length == 0) + { + tab1 = null; + } + + if (tab2 != null && tab2.Length == 0) + { + tab2 = null; + } + + if (tab1 != null && tab2 != null && tab1.Equals(tab2, StringComparison.OrdinalIgnoreCase)) + { + tab2 = null; + } + + // Override auto tab 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 + apps[packageName] = new ProcessedApp + { + PackageName = apps[entry.Key].PackageName, + Index = apps[entry.Key].Index, + AppName = appName, + AutoTabName = autoTabName ?? apps[entry.Key].AutoTabName, + Tab1Name = tab1 ?? apps[entry.Key].Tab1Name, + Tab2Name = tab2 ?? apps[entry.Key].Tab2Name, + }; + } + } + catch (Exception e) + { + Debug.Log(string.Format("Failed to process json app names: {0}", e.Message)); + return; + } + } + + private static void ProcessAppNameOverrideTxtFile(Dictionary apps, string appNameOverrideFilePath) { // Override app names, if any // This is just a file with comma-separated packageName,appName[,category1[, category2]] // Category1 and category2 are optional categories (tabs). Debug.Log("Found file: " + appNameOverrideFilePath); - string[] lines = File.ReadAllLines(appNameOverrideFilePath); + string[] lines = File.ReadAllLines(appNameOverrideFilePath, Encoding.UTF8); foreach (string line in lines) { line.Trim(); @@ -206,7 +304,7 @@ namespace QuestAppLauncher tab2 = null; } - // Override auto tabe name if custom name matches built-in tab name + // Override auto tab name if custom name matches built-in tab name if (tab1 != null && Auto_Tabs.Contains(tab1, StringComparer.OrdinalIgnoreCase)) { autoTabName = tab1; diff --git a/Assets/Scripts/AssetsDownloader.cs b/Assets/Scripts/AssetsDownloader.cs index 3639df8..6572135 100644 --- a/Assets/Scripts/AssetsDownloader.cs +++ b/Assets/Scripts/AssetsDownloader.cs @@ -131,7 +131,7 @@ namespace QuestAppLauncher // Rate limit update checks to one per couple of minutes, to avoid GitHub's rate limit if (!forceCheck && DateTime.Now.Subtract(manifest.LastUpdated).TotalMinutes < RateLimitInMins) { - Debug.LogFormat("Exceeded rate limit of {0} - last checked for update on {1}", RateLimitInMins, manifest.LastUpdated); + Debug.LogFormat("Exceeded rate limit of {0} mins - last checked for update on {1}", RateLimitInMins, manifest.LastUpdated); return false; } @@ -332,9 +332,10 @@ namespace QuestAppLauncher var url = property["url"].Value(); var name = property["name"].Value(); - // For now, simply accept any iconpack*.zip and appnames*.txt. + // For now, simply accept any iconpack*.zip and appnames*.txt/json. if ((name.StartsWith("iconpack") && name.EndsWith(".zip")) || - (name.StartsWith("appnames") && name.EndsWith(".txt"))) + (name.StartsWith("appnames") && name.EndsWith(".txt")) || + (name.StartsWith("appnames") && name.EndsWith(".json"))) { assetsInfo[name] = new AssetInfo { RepoUri = repoUri, Url = url, UpdatedAt = updatedAt, TagName = tagName }; }