Skip to content

Commit e0cf99d

Browse files
author
ComputerElite
committed
QoL improvements
1 parent 4c91ce9 commit e0cf99d

File tree

7 files changed

+175
-8
lines changed

7 files changed

+175
-8
lines changed

Assets/html/index.html

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
Backup
2323
<div class="contentHeaderDescription">Backup your game and restore backups</div>
2424
</div>
25-
<div>Backups of <div class="inline packageName">some game</div></div>
25+
<div>Backups of <div class="inline packageName">some game</div> (<div id="size" class="inline"></div>)</div>
2626
<div class="smallListContainer">
2727
<div id="backupList" class="list">
2828
</div>
@@ -36,6 +36,10 @@
3636
<div class="button" id="restoreBackup">Restore Backup</div>
3737
<div class="buttonLabel">Restores the selected Backup</div>
3838
</div>
39+
<div class="buttonContainer">
40+
<div class="button" id="deleteBackup">Delete Backup</div>
41+
<div class="buttonLabel">Deletes the selected Backup</div>
42+
</div>
3943
<div id="restoreTextBox" class="textBox"></div>
4044
</div>
4145

@@ -65,6 +69,11 @@
6569
<div class="button" id="changeApp">Change app</div>
6670
<div class="buttonLabel">Change the app you want to manage</div>
6771
</div>
72+
<div class="space">
73+
All Backups together take up <b class="inline totalSize"></b> of space on your Device.
74+
<br>
75+
You can delete Backups in the Backup section
76+
</div>
6877
<div class="about">
6978
Quest App Version Switcher Version <div id="version" class="inline"></div>
7079
Accessible via browser at:
@@ -75,6 +84,23 @@
7584
</div>
7685
</div>
7786

87+
<div class="listContainer darken hidden" id="deleteContainer">
88+
<div class="restoreStep" id="step6">
89+
<div class="contentHeader headerMargin">
90+
Confirm
91+
</div>
92+
Do you really want to delete <div class="selectedBackupName inline"></div> of <div class="inline packageName">some game</div>?
93+
<div class="buttonSelectionContainer">
94+
<div class="buttonContainer">
95+
<div class="button" id="abortDelete">No! Abort!</div>
96+
</div>
97+
<div class="buttonContainer buttonMargin">
98+
<div class="button" id="delete">Yes. Delete the Backup</div>
99+
</div>
100+
</div>
101+
</div>
102+
</div>
103+
78104
<div class="listContainer darken hidden" id="restoreContainer">
79105
<div id="step1" class="restoreStep">
80106
<div class="contentHeader headerMargin">
@@ -177,9 +203,10 @@
177203
})
178204
fetch("backups?package=" + config.currentApp).then(res => res.json().then(res => {
179205
document.getElementById("backupList").innerHTML = ""
206+
document.getElementById("size").innerHTML = res.backupsSizeString
180207
if(res.backups) {
181208
res.backups.forEach(backup => {
182-
document.getElementById("backupList").innerHTML += `<div class="listItem${backup.backupName == selectedBackup ? " listItemSelected" : ""}" value="${backup.backupName}">${backup.backupName}</div>`
209+
document.getElementById("backupList").innerHTML += `<div class="listItem${backup.backupName == selectedBackup ? " listItemSelected" : ""}" value="${backup.backupName}">${backup.backupName} (${backup.backupSizeString})</div>`
183210
})
184211
}
185212
if(document.getElementById("backupList").innerHTML == "") document.getElementById("backupList").innerHTML = `<div class="listItem" value="">No Backups</div>`
@@ -192,6 +219,13 @@
192219
loadingBackups = false
193220
}))
194221
}))
222+
fetch("allbackups").then(res => {
223+
res.text().then(text =>{
224+
Array.prototype.forEach.call(document.getElementsByClassName("totalSize"), i => {
225+
i.innerHTML = text
226+
})
227+
})
228+
})
195229
fetch("questappversionswitcher/about").then(res => res.json().then(res => {
196230
document.getElementById("version").innerHTML = res.version
197231
document.getElementById("ips").innerHTML = ""
@@ -405,6 +439,42 @@
405439
e.className = `restoreStep${ e.id == "step" + step ? "" : " hidden"}`
406440
})
407441
}
442+
443+
function CloseDeletePopup() {
444+
document.getElementById("deleteContainer").className = "listContainer darken hidden"
445+
GotoStep(6)
446+
}
447+
448+
function OpenDeletePopup() {
449+
CloseDeletePopup()
450+
document.getElementById("deleteContainer").className = "listContainer darken"
451+
}
452+
453+
document.getElementById("deleteBackup").onclick = () => {
454+
OpenDeletePopup()
455+
}
456+
457+
document.getElementById("delete").onclick = () => {
458+
CloseDeletePopup()
459+
TextBoxText("restoreTextBox", "Deleting Backup. Please wait.")
460+
fetch("/backup?package=" + config.currentApp + "&backupname=" + selectedBackup, {
461+
method: "DELETE"
462+
}).then(res => {
463+
res.text().then(text => {
464+
if(res.status == 200) {
465+
TextBoxGood("restoreTextBox", text)
466+
UpdateUI()
467+
} else {
468+
TextBoxError("restoreTextBox", text)
469+
UpdateUI()
470+
}
471+
})
472+
})
473+
}
474+
475+
document.getElementById("abortDelete").onclick = () => {
476+
CloseDeletePopup()
477+
}
408478

409479

410480

Assets/html/style.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ code {
201201
width: 100%;
202202
}
203203

204+
.space {
205+
margin-top: 40px;
206+
}
204207

205208
.lds-ellipsis {
206209
display: inline-block;

ClientModels.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,24 @@ public class AppBackup
1313
public string backupName { get; set; } = "";
1414
public string backupLocation { get; set; } = "";
1515
public bool containsGamedata { get; set; } = false;
16+
public long backupSize { get; set; } = 0;
17+
public string backupSizeString { get; set; } = "";
1618

17-
public AppBackup(string name, bool gamedata, string location)
19+
public AppBackup(string name, bool gamedata, string location, long size, string sizestr)
1820
{
1921
this.backupName = name;
2022
this.containsGamedata = gamedata;
2123
this.backupLocation = location;
24+
this.backupSize = size;
25+
this.backupSizeString = sizestr;
2226
}
2327
}
2428

2529
public class BackupList
2630
{
2731
public List<AppBackup> backups { get; set; } = new List<AppBackup>();
2832
public string lastRestored { get; set; } = "";
33+
public long backupsSize { get; set; } = 0;
34+
public string backupsSizeString { get; set; } = "";
2935
}
3036
}

ComputerUtils/ComputerUtils.FileManaging.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,27 @@ namespace ComputerUtils.FileManaging
66
{
77
public class FileManager
88
{
9+
public static long GetDirSize(string dir)
10+
{
11+
return GetDirSize(new DirectoryInfo(dir));
12+
}
13+
14+
public static long GetDirSize(DirectoryInfo d)
15+
{
16+
long size = 0;
17+
FileInfo[] fis = d.GetFiles();
18+
foreach (FileInfo fi in fis)
19+
{
20+
size += fi.Length;
21+
}
22+
DirectoryInfo[] dis = d.GetDirectories();
23+
foreach (DirectoryInfo di in dis)
24+
{
25+
size += GetDirSize(di);
26+
}
27+
return size;
28+
}
29+
930
public static string GetParentDirIfExisting(string dir)
1031
{
1132
try

Properties/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.ComputerElite.questappversionswitcher" android:installLocation="auto">
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0.1" package="com.ComputerElite.questappversionswitcher" android:installLocation="preferExternal" android:versionCode="2">
33
<uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
44
<uses-permission android:name="oculus.permission.handtracking" />
55
<uses-permission android:name="com.oculus.permission.HAND_TRACKING" />

QuestAppVersionSwitcher.csproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@
3838
<AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
3939
<AndroidLinkMode>None</AndroidLinkMode>
4040
<EmbedAssembliesIntoApk>False</EmbedAssembliesIntoApk>
41+
<AotAssemblies>false</AotAssemblies>
42+
<EnableLLVM>false</EnableLLVM>
43+
<AndroidEnableProfiledAot>false</AndroidEnableProfiledAot>
44+
<BundleAssemblies>false</BundleAssemblies>
4145
</PropertyGroup>
4246
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
4347
<DebugSymbols>True</DebugSymbols>
@@ -51,6 +55,10 @@
5155
<AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
5256
<AndroidLinkMode>SdkOnly</AndroidLinkMode>
5357
<EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
58+
<AotAssemblies>false</AotAssemblies>
59+
<EnableLLVM>false</EnableLLVM>
60+
<AndroidEnableProfiledAot>false</AndroidEnableProfiledAot>
61+
<BundleAssemblies>false</BundleAssemblies>
5462
</PropertyGroup>
5563
<ItemGroup>
5664
<Reference Include="System" />

WebServer.cs

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,11 @@ public void Start()
177177
string gameDataDir = CoreService.coreVars.AndroidAppLocation + package;
178178
try
179179
{
180+
text = "Copying APK. Please wait until it has finished. This can take up to 2 minutes";
181+
code = 202;
180182
File.Copy(apkDir, backupDir + "app.apk");
183+
text = "Copying App Data. Please wait until it has finished. This can take up to 2 minutes";
184+
code = 202;
181185
FileManager.DirectoryCopy(gameDataDir, backupDir + package, true);
182186
} catch (Exception e)
183187
{
@@ -194,6 +198,29 @@ public void Start()
194198
serverRequest.SendString(text, "text/plain", code);
195199
return true;
196200
}));
201+
server.AddRoute("DELETE", "/backup", new Func<ServerRequest, bool>(serverRequest =>
202+
{
203+
if (serverRequest.queryString.Get("package") == null)
204+
{
205+
serverRequest.SendString("package key needed", "text/plain", 400);
206+
return true;
207+
}
208+
if (serverRequest.queryString.Get("backupname") == null)
209+
{
210+
serverRequest.SendString("backupname key needed", "text/plain", 400);
211+
return true;
212+
}
213+
string package = serverRequest.queryString.Get("package");
214+
string backupname = serverRequest.queryString.Get("backupname");
215+
string backupDir = CoreService.coreVars.QAVSBackupDir + package + "/" + backupname + "/";
216+
if (!Directory.Exists(backupDir))
217+
{
218+
serverRequest.SendString("The Backup you want to delete doesn't exist.", "text/plain", 400);
219+
}
220+
Directory.Delete(backupDir, true);
221+
serverRequest.SendString("Deleted " + backupname + " of " + package);
222+
return true;
223+
}));
197224
server.AddRoute("POST", "/restoreapp", new Func<ServerRequest, bool>(serverRequest =>
198225
{
199226
if (serverRequest.queryString.Get("package") == null)
@@ -224,6 +251,11 @@ public void Start()
224251
serverRequest.SendString("This backup doesn't exist", "text/plain", 400);
225252
return true;
226253
}
254+
if(!File.Exists(backupDir + "app.apk"))
255+
{
256+
serverRequest.SendString("Critical: APK doesn't exist in Backup. This Backup is useless. Please restart the app and choose a different one.", "text/plain", 500);
257+
return true;
258+
}
227259
AndroidService.InitiateInstallApk(backupDir + "app.apk");
228260
serverRequest.SendString("Started apk install", "text/plain", 200);
229261
return true;
@@ -264,6 +296,11 @@ public void Start()
264296
return true;
265297
}
266298
string gameDataDir = CoreService.coreVars.AndroidAppLocation + package;
299+
if(!Directory.Exists(backupDir + package))
300+
{
301+
serverRequest.SendString("This backup doesn't contain a game data backup. Please skip this step", "text/plain", 400);
302+
return true;
303+
}
267304
try
268305
{
269306
FileManager.DirectoryCopy(backupDir + package, gameDataDir, true);
@@ -276,6 +313,11 @@ public void Start()
276313
serverRequest.SendString("Game data restored", "text/plain", 200);
277314
return true;
278315
}));
316+
server.AddRoute("GET", "/allbackups", new Func<ServerRequest, bool>(serverRequest =>
317+
{
318+
serverRequest.SendString(ByteSizeToString(FileManager.GetDirSize(CoreService.coreVars.QAVSBackupDir)));
319+
return true;
320+
}));
279321
server.AddRouteFile("/facts.png", "facts.png");
280322
server.StartServer(50001);
281323
Thread.Sleep(1000);
@@ -288,12 +330,29 @@ public BackupList GetBackups(string package)
288330
BackupList backups = new BackupList();
289331
foreach (string d in Directory.GetDirectories(backupDir))
290332
{
291-
backups.backups.Add(new AppBackup(Path.GetFileName(d), Directory.Exists(d + "/GameData"), d));
333+
long size = FileManager.GetDirSize(d);
334+
backups.backupsSize += size;
335+
backups.backups.Add(new AppBackup(Path.GetFileName(d), Directory.Exists(d + "/GameData"), d, size, ByteSizeToString(size)));
292336
}
293337
if (File.Exists(backupDir + "lastRestored.txt")) backups.lastRestored = File.ReadAllText(backupDir + "lastRestored.txt");
338+
backups.backupsSizeString = ByteSizeToString(backups.backupsSize);
294339
return backups;
295340
}
296341

342+
public string ByteSizeToString(long input, int decimals = 2)
343+
{
344+
// TB
345+
if (input > 1099511627776) return String.Format("{0:0." + new string('#', decimals) + "}", input / 1099511627776.0) + " TB";
346+
// GB
347+
else if (input > 1073741824) return String.Format("{0:0." + new string('#', decimals) + "}", input / 1073741824.0) + " GB";
348+
// MB
349+
else if (input > 1048576) return String.Format("{0:0." + new string('#', decimals) + "}", input / 1048576.0) + " MB";
350+
// KB
351+
else if (input > 1024) return String.Format("{0:0." + new string('#', decimals) + "}", input / 1024.0) + " KB";
352+
// Bytes
353+
else return input + " Bytes";
354+
}
355+
297356
public bool IsNameFileNameSafe(string name)
298357
{
299358
foreach(char c in ReservedChars)
@@ -307,7 +366,6 @@ public List<string> GetIPs()
307366
{
308367
return server.ips;
309368
}
310-
311369
public static byte[] GetAssetBytes(string assetName)
312370
{
313371
MemoryStream ms = new MemoryStream();
@@ -331,10 +389,10 @@ public static List<string> GetAllFiles(string folder)
331389
List<string> files = new List<string>();
332390
if (!folder.EndsWith("/")) folder += "/";
333391
if (folder == "/") folder = "";
334-
foreach(string s in CoreService.assetManager.List(folder))
392+
foreach (string s in CoreService.assetManager.List(folder))
335393
{
336394
files.Add(folder + s);
337-
foreach(string ss in GetAllFiles(folder + s)) files.Add(ss);
395+
foreach (string ss in GetAllFiles(folder + s)) files.Add(ss);
338396
}
339397
return files;
340398
}
@@ -343,5 +401,6 @@ public static List<string> GetAssetFolderFileList(string assetFolder)
343401
{
344402
return new List<string>(CoreService.assetManager.List(assetFolder));
345403
}
404+
346405
}
347406
}

0 commit comments

Comments
 (0)