From 1ab81908278bbc7f82f22979ddf6722fece75388 Mon Sep 17 00:00:00 2001 From: tverona1 Date: Tue, 20 Aug 2019 23:41:09 -0700 Subject: [PATCH] Support to sort by most recent usage --- Assets/Plugins/Android/AndroidManifest.xml | 1 + Assets/Plugins/Android/AppInfo.java | 69 +- Assets/Scenes/QuestAppLauncher.unity | 1319 +++++++++++++++++++- Assets/Scripts/AppProcessor.cs | 18 +- Assets/Scripts/Config.cs | 7 + Assets/Scripts/GridPopulation.cs | 15 +- Assets/Scripts/SettingsHandler.cs | 84 ++ 7 files changed, 1495 insertions(+), 18 deletions(-) diff --git a/Assets/Plugins/Android/AndroidManifest.xml b/Assets/Plugins/Android/AndroidManifest.xml index a3cf07a..7e473fe 100644 --- a/Assets/Plugins/Android/AndroidManifest.xml +++ b/Assets/Plugins/Android/AndroidManifest.xml @@ -11,4 +11,5 @@ + \ No newline at end of file diff --git a/Assets/Plugins/Android/AppInfo.java b/Assets/Plugins/Android/AppInfo.java index e19c8f2..83b248a 100644 --- a/Assets/Plugins/Android/AppInfo.java +++ b/Assets/Plugins/Android/AppInfo.java @@ -2,17 +2,25 @@ package aaa.QuestAppLauncher.App; import com.unity3d.player.UnityPlayerActivity; import android.app.Activity; +import android.app.AppOpsManager; +import android.app.usage.UsageStats; +import android.app.usage.UsageStatsManager; +import android.content.Context; +import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageInfo; import android.content.pm.FeatureInfo; import android.content.pm.ApplicationInfo; +import android.provider.Settings; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.util.Calendar; +import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import android.os.Bundle; @@ -22,23 +30,30 @@ import android.graphics.drawable.BitmapDrawable; import java.util.List; import java.util.LinkedList; +class AppInfoInternal { + public ApplicationInfo app; + public long lastTimeUsed; +} + public class AppInfo extends UnityPlayerActivity { private static final String TAG = "AppInfo"; - private List installedApps; + private List installedApps; @Override protected void onStart() { super.onStart(); - installedApps = new LinkedList(); + installedApps = new LinkedList(); for(ApplicationInfo app : this.getPackageManager().getInstalledApplications(PackageManager.GET_META_DATA)) { if((app.flags & (ApplicationInfo.FLAG_UPDATED_SYSTEM_APP | ApplicationInfo.FLAG_SYSTEM)) > 0) { // Skip system app continue; } - installedApps.add(app); + AppInfoInternal appInfoInternal = new AppInfoInternal(); + appInfoInternal.app = app; + installedApps.add(appInfoInternal); } } @@ -47,11 +62,16 @@ public class AppInfo extends UnityPlayerActivity { } public String getPackageName(int i) { - return this.installedApps.get(i).packageName; + return this.installedApps.get(i).app.packageName; } public String getAppName(int i) { - return (String)this.getPackageManager().getApplicationLabel(installedApps.get(i)); + return (String)this.getPackageManager().getApplicationLabel(installedApps.get(i).app); + } + + public long getLastTimeUsed(int i) + { + return this.installedApps.get(i).lastTimeUsed; } public boolean isQuestApp(int i) { @@ -73,7 +93,7 @@ public class AppInfo extends UnityPlayerActivity { public boolean is2DApp(int i) { - ApplicationInfo app = this.installedApps.get(i); + ApplicationInfo app = this.installedApps.get(i).app; if (null == app.metaData) { return true; @@ -88,7 +108,7 @@ public class AppInfo extends UnityPlayerActivity { } public byte[] getIcon(int i) { - BitmapDrawable icon = (BitmapDrawable)this.getPackageManager().getApplicationIcon(installedApps.get(i)); + BitmapDrawable icon = (BitmapDrawable)this.getPackageManager().getApplicationIcon(installedApps.get(i).app); Bitmap bmp = icon.getBitmap(); ByteArrayOutputStream stream = new ByteArrayOutputStream(); bmp.compress(Bitmap.CompressFormat.JPEG, 100, stream); @@ -96,6 +116,41 @@ public class AppInfo extends UnityPlayerActivity { return byteArray; } + public boolean hasUsageStatsPermissions() { + AppOpsManager appOps = (AppOpsManager) this.getSystemService(Context.APP_OPS_SERVICE); + final int mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, android.os.Process.myUid(), this.getPackageName()); + boolean granted = mode == AppOpsManager.MODE_DEFAULT ? + (this.checkCallingOrSelfPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) == PackageManager.PERMISSION_GRANTED) + : (mode == AppOpsManager.MODE_ALLOWED); + return granted; + } + + public void grantUsageStatsPermission() { + startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)); + } + + public void processLastTimeUsed(int numDaysLookback) { + if (!hasUsageStatsPermissions()) { + Log.i(TAG, "PorcessLastTimeUsed: No permissions, so skipping"); + } + + UsageStatsManager usageStatsManager = (UsageStatsManager) this.getSystemService(Context.USAGE_STATS_SERVICE); + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.DAY_OF_MONTH, -1 * numDaysLookback); + long start = calendar.getTimeInMillis(); + long end = System.currentTimeMillis(); + Map stats = usageStatsManager.queryAndAggregateUsageStats(start, end); + + for (int i = 0; i < this.installedApps.size(); i++) { + if (stats.containsKey(getPackageName(i))) { + AppInfoInternal app = this.installedApps.get(i); + app.lastTimeUsed = stats.get(getPackageName(i)).getLastTimeStamp(); + Log.v(TAG, "Package " + getPackageName(i) + " last time stamp = " + app.lastTimeUsed); + this.installedApps.set(i, app); + } + } + } + public static void unzip(String zipFileName, String targetPath) { File outDir = new File(targetPath); diff --git a/Assets/Scenes/QuestAppLauncher.unity b/Assets/Scenes/QuestAppLauncher.unity index e1a948e..a35f8cb 100644 --- a/Assets/Scenes/QuestAppLauncher.unity +++ b/Assets/Scenes/QuestAppLauncher.unity @@ -1453,6 +1453,163 @@ Transform: type: 3} m_PrefabInstance: {fileID: 174121771} m_PrefabAsset: {fileID: 0} +--- !u!1 &177729748 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 177729749} + - component: {fileID: 177729751} + - component: {fileID: 177729750} + m_Layer: 5 + m_Name: Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &177729749 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 177729748} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 240885095} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 300, y: -75} + m_SizeDelta: {x: 600, y: 150} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &177729750 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 177729748} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Sort By + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 86 + m_fontSizeBase: 86 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 513 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 0 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 177729750} + characterCount: 7 + spriteCount: 0 + spaceCount: 1 + wordCount: 2 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &177729751 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 177729748} + m_CullTransparentMesh: 0 --- !u!1 &210908719 GameObject: m_ObjectHideFlags: 0 @@ -1489,6 +1646,84 @@ RectTransform: m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &240885094 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 240885095} + - component: {fileID: 240885096} + - component: {fileID: 240885097} + m_Layer: 5 + m_Name: Sort_Setting + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &240885095 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 240885094} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 177729749} + - {fileID: 1092056641} + - {fileID: 1829862260} + m_Father: {fileID: 883330324} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 150, y: -775} + m_SizeDelta: {x: 100, y: 150} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &240885096 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 240885094} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 0 + m_ChildControlHeight: 0 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 +--- !u!114 &240885097 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 240885094} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2fafe2cfe61f6974895a912c3755e8f1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_AllowSwitchOff: 0 --- !u!1 &247836998 GameObject: m_ObjectHideFlags: 0 @@ -1760,11 +1995,11 @@ RectTransform: - {fileID: 987583755} - {fileID: 87081339} m_Father: {fileID: 883330324} - m_RootOrder: 2 + m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 500, y: -775} + m_AnchoredPosition: {x: 500, y: -1025} m_SizeDelta: {x: 800, y: 150} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &302656574 @@ -2736,6 +2971,82 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &455413003 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 455413004} + - component: {fileID: 455413006} + - component: {fileID: 455413005} + m_Layer: 5 + m_Name: Background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &455413004 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 455413003} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1629902000} + m_Father: {fileID: 1480305969} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 100, y: -75} + m_SizeDelta: {x: 200, y: 150} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &455413005 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 455413003} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.24313727, g: 0.427451, b: 0.6627451, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &455413006 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 455413003} + m_CullTransparentMesh: 0 --- !u!1 &455930354 GameObject: m_ObjectHideFlags: 0 @@ -3270,11 +3581,11 @@ RectTransform: - {fileID: 1106898771} - {fileID: 129491542} m_Father: {fileID: 883330324} - m_RootOrder: 5 + m_RootOrder: 6 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 150, y: -1500} + m_AnchoredPosition: {x: 150, y: -1750} m_SizeDelta: {x: 100, y: 100} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &572537056 @@ -3526,11 +3837,11 @@ RectTransform: - {fileID: 4342933} - {fileID: 2063273159} m_Father: {fileID: 883330324} - m_RootOrder: 4 + m_RootOrder: 5 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 500, y: -1275} + m_AnchoredPosition: {x: 500, y: -1525} m_SizeDelta: {x: 800, y: 150} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &585330017 @@ -4953,6 +5264,7 @@ RectTransform: m_Children: - {fileID: 1133097218} - {fileID: 2027300713} + - {fileID: 240885095} - {fileID: 302656573} - {fileID: 949458750} - {fileID: 585330016} @@ -5060,6 +5372,9 @@ MonoBehaviour: tabsCustomTop: {fileID: 247837002} tabsCustomLeft: {fileID: 1462980089} tabsCustomRight: {fileID: 1158989063} + sortAZ: {fileID: 1092056644} + sortMostRecent: {fileID: 1480305972} + usageStatsPermText: {fileID: 907885703} --- !u!65 &883330329 BoxCollider: m_ObjectHideFlags: 0 @@ -5230,6 +5545,163 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 907338447} m_CullTransparentMesh: 0 +--- !u!1 &907885703 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 907885704} + - component: {fileID: 907885706} + - component: {fileID: 907885705} + m_Layer: 5 + m_Name: UsageStats_Permission_Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &907885704 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 907885703} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1829862260} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &907885705 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 907885703} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Requires UsageStats permissions. Select to set. + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 40 + m_fontSizeBase: 40 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 257 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: 0 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 3.513392, y: 0, z: -1298.6443, w: 0} + m_textInfo: + textComponent: {fileID: 907885705} + characterCount: 47 + spriteCount: 0 + spaceCount: 5 + wordCount: 6 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &907885706 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 907885703} + m_CullTransparentMesh: 0 --- !u!1 &949458749 GameObject: m_ObjectHideFlags: 0 @@ -5263,11 +5735,11 @@ RectTransform: - {fileID: 1398590894} - {fileID: 604462432} m_Father: {fileID: 883330324} - m_RootOrder: 3 + m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 500, y: -1025} + m_AnchoredPosition: {x: 500, y: -1275} m_SizeDelta: {x: 800, y: 150} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &949458751 @@ -5447,6 +5919,320 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 987583754} m_CullTransparentMesh: 0 +--- !u!1 &1004538039 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1004538040} + - component: {fileID: 1004538042} + - component: {fileID: 1004538041} + m_Layer: 5 + m_Name: Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1004538040 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1004538039} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1092056641} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 375, y: -75} + m_SizeDelta: {x: 250, y: 150} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1004538041 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1004538039} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: A - Z + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 86 + m_fontSizeBase: 86 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 513 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 0 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 1004538041} + characterCount: 5 + spriteCount: 0 + spaceCount: 2 + wordCount: 3 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1004538042 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1004538039} + m_CullTransparentMesh: 0 +--- !u!1 &1026875225 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1026875226} + - component: {fileID: 1026875228} + - component: {fileID: 1026875227} + m_Layer: 5 + m_Name: Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1026875226 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1026875225} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1480305969} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 475, y: -75} + m_SizeDelta: {x: 450, y: 150} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1026875227 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1026875225} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_text: Most Recent + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_outlineColor: + serializedVersion: 2 + rgba: 4278190080 + m_fontSize: 86 + m_fontSizeBase: 86 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_textAlignment: 513 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 0 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_firstOverflowCharacterIndex: -1 + m_linkedTextComponent: {fileID: 0} + m_isLinkedTextComponent: 0 + m_isTextTruncated: 0 + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_ignoreRectMaskCulling: 0 + m_ignoreCulling: 1 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_VertexBufferAutoSizeReduction: 1 + m_firstVisibleCharacter: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_textInfo: + textComponent: {fileID: 1026875227} + characterCount: 11 + spriteCount: 0 + spaceCount: 1 + wordCount: 2 + linkCount: 0 + lineCount: 1 + pageCount: 1 + materialCount: 1 + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_spriteAnimator: {fileID: 0} + m_hasFontAssetChanged: 0 + m_subTextObjects: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1026875228 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1026875225} + m_CullTransparentMesh: 0 --- !u!1 &1051081550 GameObject: m_ObjectHideFlags: 0 @@ -5867,6 +6653,133 @@ RectTransform: m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: -20, y: -20} m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1092056640 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1092056641} + - component: {fileID: 1092056644} + - component: {fileID: 1092056643} + - component: {fileID: 1092056642} + m_Layer: 5 + m_Name: Alphabetically_Toggle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1092056641 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1092056640} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1181631556} + - {fileID: 1004538040} + m_Father: {fileID: 240885095} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 850, y: -75} + m_SizeDelta: {x: 500, y: 150} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1092056642 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1092056640} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 0 + m_Spacing: 50 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 0 + m_ChildControlHeight: 0 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 +--- !u!65 &1092056643 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1092056640} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 500, y: 150, z: 0.05} + m_Center: {x: 0, y: 0, z: 0} +--- !u!114 &1092056644 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1092056640} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1181631557} + toggleTransition: 1 + graphic: {fileID: 2017584416} + m_Group: {fileID: 240885097} + onValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Toggle+ToggleEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null + m_IsOn: 1 --- !u!1 &1096116666 GameObject: m_ObjectHideFlags: 0 @@ -7306,6 +8219,82 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1175856089} m_CullTransparentMesh: 0 +--- !u!1 &1181631555 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1181631556} + - component: {fileID: 1181631558} + - component: {fileID: 1181631557} + m_Layer: 5 + m_Name: Background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1181631556 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1181631555} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 2017584415} + m_Father: {fileID: 1092056641} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 100, y: -75} + m_SizeDelta: {x: 200, y: 150} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1181631557 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1181631555} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.24313727, g: 0.427451, b: 0.6627451, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1181631558 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1181631555} + m_CullTransparentMesh: 0 --- !u!4 &1192133537 stripped Transform: m_CorrespondingSourceObject: {fileID: 487254, guid: 126d619cf4daa52469682f85c1378b4a, @@ -9450,6 +10439,133 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1471555291} m_CullTransparentMesh: 0 +--- !u!1 &1480305968 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1480305969} + - component: {fileID: 1480305972} + - component: {fileID: 1480305971} + - component: {fileID: 1480305970} + m_Layer: 5 + m_Name: MostRecent_Toggle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1480305969 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1480305968} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 455413004} + - {fileID: 1026875226} + m_Father: {fileID: 1829862260} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1480305970 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1480305968} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 3 + m_Spacing: 50 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 0 + m_ChildControlHeight: 0 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 +--- !u!65 &1480305971 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1480305968} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 600, y: 150, z: 0.05} + m_Center: {x: 0, y: 0, z: 0} +--- !u!114 &1480305972 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1480305968} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 455413005} + toggleTransition: 1 + graphic: {fileID: 1629902001} + m_Group: {fileID: 240885097} + onValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Toggle+ToggleEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null + m_IsOn: 0 --- !u!1 &1550751410 GameObject: m_ObjectHideFlags: 0 @@ -10155,6 +11271,81 @@ MonoBehaviour: m_EditorClassIdentifier: content: {fileID: 858538435} trackingSpace: {fileID: 881994610} +--- !u!1 &1629901999 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1629902000} + - component: {fileID: 1629902002} + - component: {fileID: 1629902001} + m_Layer: 5 + m_Name: Checkmark + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1629902000 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1629901999} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 455413004} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 150, y: 150} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1629902001 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1629901999} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 21300000, guid: 01674f533e98ba544a7bb592e2f52669, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1629902002 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1629901999} + m_CullTransparentMesh: 0 --- !u!1 &1644097589 GameObject: m_ObjectHideFlags: 0 @@ -11260,6 +12451,43 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1823234009} m_CullTransparentMesh: 0 +--- !u!1 &1829862259 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1829862260} + m_Layer: 5 + m_Name: MostRecent + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1829862260 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1829862259} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1480305969} + - {fileID: 907885704} + m_Father: {fileID: 240885095} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 1400, y: -75} + m_SizeDelta: {x: 600, y: 150} + m_Pivot: {x: 0.5, y: 0.5} --- !u!1 &1839702706 GameObject: m_ObjectHideFlags: 0 @@ -12478,6 +13706,81 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2009369171} m_CullTransparentMesh: 0 +--- !u!1 &2017584414 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2017584415} + - component: {fileID: 2017584417} + - component: {fileID: 2017584416} + m_Layer: 5 + m_Name: Checkmark + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2017584415 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2017584414} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1181631556} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 150, y: 150} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2017584416 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2017584414} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 21300000, guid: 01674f533e98ba544a7bb592e2f52669, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &2017584417 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2017584414} + m_CullTransparentMesh: 0 --- !u!1 &2025011530 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/AppProcessor.cs b/Assets/Scripts/AppProcessor.cs index 19948b1..dddf27c 100644 --- a/Assets/Scripts/AppProcessor.cs +++ b/Assets/Scripts/AppProcessor.cs @@ -23,6 +23,7 @@ namespace QuestAppLauncher public string Tab1Name; public string Tab2Name; public string IconPath; + public long LastTimeUsed; } public class AppProcessor @@ -60,6 +61,9 @@ namespace QuestAppLauncher public const string Tab_2D = "2D"; public const string Tab_All = "All"; + // LastUsage lookback days + const int LastUsedLookbackDays = 30; + public static readonly string[] Auto_Tabs = { Tab_Quest, Tab_Go, Tab_2D }; public static Dictionary ProcessApps(Config config) @@ -79,6 +83,14 @@ namespace QuestAppLauncher int numApps = currentActivity.Call("getSize"); Debug.Log("# installed apps: " + numApps); + var processedLastTimeUsed = false; + if (config.sortMode.Equals(Config.Sort_MostRecent, StringComparison.OrdinalIgnoreCase)) + { + // Process last time used for each app + currentActivity.Call("processLastTimeUsed", LastUsedLookbackDays); + processedLastTimeUsed = true; + } + // Add current package name to excludedPackageNames to filter it out excludedPackageNames.Add(currentActivity.Call("getPackageName")); @@ -102,6 +114,7 @@ namespace QuestAppLauncher { var packageName = currentActivity.Call("getPackageName", i); var appName = currentActivity.Call("getAppName", i); + var lastTimeUsed = processedLastTimeUsed ? currentActivity.Call("getLastTimeUsed", i) : 0; if (excludedPackageNames.Contains(packageName)) { @@ -132,7 +145,8 @@ namespace QuestAppLauncher tabName = Tab_Go; } - apps.Add(packageName, new ProcessedApp { PackageName = packageName, Index = i, AutoTabName = tabName, AppName = appName }); + apps.Add(packageName, new ProcessedApp { PackageName = packageName, Index = i, + AutoTabName = tabName, AppName = appName, LastTimeUsed = lastTimeUsed }); Debug.LogFormat("[{0}] package: {1}, name: {2}, auto tab: {3}", i, packageName, appName, tabName); } @@ -239,6 +253,7 @@ namespace QuestAppLauncher AutoTabName = autoTabName ?? apps[entry.Key].AutoTabName, Tab1Name = tab1 ?? apps[entry.Key].Tab1Name, Tab2Name = tab2 ?? apps[entry.Key].Tab2Name, + LastTimeUsed = apps[entry.Key].LastTimeUsed }; } } @@ -326,6 +341,7 @@ namespace QuestAppLauncher AutoTabName = autoTabName ?? apps[entry[0]].AutoTabName, Tab1Name = tab1 ?? apps[entry[0]].Tab1Name, Tab2Name = tab2 ?? apps[entry[0]].Tab2Name, + LastTimeUsed = apps[entry[0]].LastTimeUsed }; } } diff --git a/Assets/Scripts/Config.cs b/Assets/Scripts/Config.cs index 93f6349..4597467 100644 --- a/Assets/Scripts/Config.cs +++ b/Assets/Scripts/Config.cs @@ -20,6 +20,10 @@ namespace QuestAppLauncher public const string Category_Left = "left"; public const string Category_Right = "right"; + // Sort settings + public const string Sort_AZ = "az"; + public const string Sort_MostRecent = "mostRecent"; + // Download repos public const string DownloadRepo_Type_GitHub = "github"; public const string DownloadRepo_Default = @"tverona1/QuestAppLauncher_Assets/releases/latest"; @@ -47,6 +51,9 @@ namespace QuestAppLauncher // Grid size, specified as cols x rows public GridSize gridSize = new GridSize(); + // Sort mode + public string sortMode = Sort_AZ; + // Whether to show 2D apps public bool show2D = false; diff --git a/Assets/Scripts/GridPopulation.cs b/Assets/Scripts/GridPopulation.cs index eafd55c..c0aeb6b 100644 --- a/Assets/Scripts/GridPopulation.cs +++ b/Assets/Scripts/GridPopulation.cs @@ -17,6 +17,17 @@ namespace QuestAppLauncher /// public class GridPopulation : MonoBehaviour { + public class AppComparer : IComparer + { + public int Compare(ProcessedApp x, ProcessedApp y) + { + // Order by last used and then alphabetical to break ties + return (x.LastTimeUsed != y.LastTimeUsed) ? + (y.LastTimeUsed - x.LastTimeUsed > 0 ? 1 : -1) : + string.Compare(x.AppName, y.AppName, true); + } + } + // Grid container game object public GameObject panelContainer; @@ -168,8 +179,8 @@ namespace QuestAppLauncher } // Populate grid with app information (name & icon) - // Sort by app name - foreach (var app in apps.OrderBy(key => key.Value.AppName)) + // Sort by custom comparer + foreach (var app in apps.OrderBy(key => key.Value, new AppComparer())) { // Add to all tab await AddCellToGridAsync(app.Value, gridContents[AppProcessor.Tab_All].transform); diff --git a/Assets/Scripts/SettingsHandler.cs b/Assets/Scripts/SettingsHandler.cs index ada576a..e7631f9 100644 --- a/Assets/Scripts/SettingsHandler.cs +++ b/Assets/Scripts/SettingsHandler.cs @@ -33,6 +33,11 @@ namespace QuestAppLauncher public Toggle tabsCustomLeft; public Toggle tabsCustomRight; + public Toggle sortAZ; + public Toggle sortMostRecent; + + public GameObject usageStatsPermText; + private bool deletedHiddenAppsFile = false; private Config config = null; @@ -60,6 +65,9 @@ namespace QuestAppLauncher var rowsText = this.gridRowsText.GetComponent(); rowsText.text = string.Format("{0} Rows", this.config.gridSize.rows); + // initialize sort mode + InitializeSortMode(); + // Set 2D toggle this.show2DToggle.GetComponent().SetIsOnWithoutNotify(this.config.show2D); @@ -144,6 +152,65 @@ namespace QuestAppLauncher rowsText.text = string.Format("{0} Rows", rows); } + private bool HasUsageStatsPermissions() + { + // Check if we have UsageStats permission + using (AndroidJavaClass unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) + using (AndroidJavaObject currentActivity = unity.GetStatic("currentActivity")) + { + var hasUsageStatsPermissions = currentActivity.Call("hasUsageStatsPermissions"); + Debug.LogFormat("UsageStatsPermission: {0}", hasUsageStatsPermissions); + return hasUsageStatsPermissions; + } + } + + private void InitializeSortMode() + { + bool hasUsageStatsPermissions = HasUsageStatsPermissions(); + + // Indicate whether we need to get permission + this.usageStatsPermText.SetActive(!hasUsageStatsPermissions); + + if (hasUsageStatsPermissions && + this.config.sortMode.Equals(Config.Sort_MostRecent, StringComparison.OrdinalIgnoreCase)) + { + // Have UsageStats permission, so set it to on + this.sortMostRecent.isOn = true; + } + else + { + // Default is to sort by AZ + this.sortAZ.isOn = true; + } + + this.sortMostRecent.onValueChanged.AddListener((bool isOn) => { + if (isOn) + { + // Re-check permissions + bool hasPerms = HasUsageStatsPermissions(); + + // Indicate whether we need to get permission + this.usageStatsPermText.SetActive(!hasPerms); + + if (!hasPerms) + { + this.sortMostRecent.SetIsOnWithoutNotify(false); + this.sortAZ.SetIsOnWithoutNotify(true); + + // Ask for permissions + using (AndroidJavaClass unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) + using (AndroidJavaObject currentActivity = unity.GetStatic("currentActivity")) + { + currentActivity.Call("grantUsageStatsPermission"); + + // Quest doesn't like multiple apps running - kill ourself + UnityEngine.Application.Quit(); + } + } + } + }); + } + private void PersistConfig() { bool saveConfig = false; @@ -160,6 +227,23 @@ namespace QuestAppLauncher saveConfig = true; } + // Update sort mode + string sortMode; + if (this.sortMostRecent.isOn) + { + sortMode = Config.Sort_MostRecent; + } + else + { + sortMode = Config.Sort_AZ; + } + + if (!this.config.sortMode.Equals(sortMode, StringComparison.OrdinalIgnoreCase)) + { + this.config.sortMode = sortMode; + saveConfig = true; + } + // Update 2D toggle var show2D = this.show2DToggle.GetComponent().isOn; if (show2D != this.config.show2D)